blob: cdfca5b3a7c3911c6f8686f113a40396b522f220 [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) {
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200445 curproxy->comp = calloc(1, sizeof(*curproxy->comp));
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100446 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
Amaury Denoyelle36b53662020-09-18 15:59:39 +0200482 free(defproxy.conf.file);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100483 free(defproxy.check_command);
484 free(defproxy.check_path);
485 free(defproxy.cookie_name);
486 free(defproxy.rdp_cookie_name);
487 free(defproxy.dyncookie_key);
488 free(defproxy.cookie_domain);
Christopher Faulet2f533902020-01-21 11:06:48 +0100489 free(defproxy.cookie_attrs);
Willy Tarreau4c03d1c2019-01-14 15:23:54 +0100490 free(defproxy.lbprm.arg_str);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100491 free(defproxy.capture_name);
492 free(defproxy.monitor_uri);
493 free(defproxy.defbe.name);
494 free(defproxy.conn_src.iface_name);
495 free(defproxy.fwdfor_hdr_name);
496 defproxy.fwdfor_hdr_len = 0;
497 free(defproxy.orgto_hdr_name);
498 defproxy.orgto_hdr_len = 0;
499 free(defproxy.server_id_hdr_name);
500 defproxy.server_id_hdr_len = 0;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100501
502 if (defproxy.conf.logformat_string != default_http_log_format &&
503 defproxy.conf.logformat_string != default_tcp_log_format &&
504 defproxy.conf.logformat_string != clf_http_log_format)
505 free(defproxy.conf.logformat_string);
506
507 free(defproxy.conf.uniqueid_format_string);
508 free(defproxy.conf.lfs_file);
509 free(defproxy.conf.uif_file);
510 chunk_destroy(&defproxy.log_tag);
511 free_email_alert(&defproxy);
512
513 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
514 free(defproxy.conf.logformat_sd_string);
515 free(defproxy.conf.lfsd_file);
516
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100517 proxy_release_conf_errors(&defproxy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100518
Christopher Faulet5d503fc2020-03-30 20:34:34 +0200519 deinit_proxy_tcpcheck(&defproxy);
520
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100521 /* we cannot free uri_auth because it might already be used */
522 init_default_instance();
523 curproxy = &defproxy;
524 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
525 curproxy->conf.args.line = curproxy->conf.line = linenum;
526 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
527 goto out;
528 }
529 else if (curproxy == NULL) {
530 ha_alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534
535 /* update the current file and line being parsed */
536 curproxy->conf.args.file = curproxy->conf.file;
537 curproxy->conf.args.line = linenum;
538
539 /* Now let's parse the proxy-specific keywords */
540 if (!strcmp(args[0], "server") ||
541 !strcmp(args[0], "default-server") ||
542 !strcmp(args[0], "server-template")) {
Emeric Brund3db3842020-07-21 16:54:36 +0200543 err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1, 0, 0);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100544 if (err_code & ERR_FATAL)
545 goto out;
546 }
547 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
548 struct listener *l;
549 int cur_arg;
550
551 if (curproxy == &defproxy) {
552 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
557 err_code |= ERR_WARN;
558
559 if (!*(args[1])) {
560 ha_alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
561 file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565
566 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
567
568 /* use default settings for unix sockets */
Willy Tarreau6e459d72020-09-03 07:09:09 +0200569 bind_conf->settings.ux.uid = global.unix_bind.ux.uid;
570 bind_conf->settings.ux.gid = global.unix_bind.ux.gid;
571 bind_conf->settings.ux.mode = global.unix_bind.ux.mode;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100572
573 /* NOTE: the following line might create several listeners if there
574 * are comma-separated IPs or port ranges. So all further processing
575 * will have to be applied to all listeners created after last_listen.
576 */
577 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
578 if (errmsg && *errmsg) {
579 indent_msg(&errmsg, 2);
580 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
581 }
582 else
583 ha_alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
584 file, linenum, args[0], args[1]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588
589 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
590 /* Set default global rights and owner for unix bind */
591 global.maxsock++;
592 }
593
594 cur_arg = 2;
595 while (*(args[cur_arg])) {
596 static int bind_dumped;
597 struct bind_kw *kw;
598 char *err;
599
600 kw = bind_find_kw(args[cur_arg]);
601 if (kw) {
602 char *err = NULL;
603 int code;
604
605 if (!kw->parse) {
606 ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
607 file, linenum, args[0], args[1], args[cur_arg]);
608 cur_arg += 1 + kw->skip ;
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612
613 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
614 err_code |= code;
615
616 if (code) {
617 if (err && *err) {
618 indent_msg(&err, 2);
Emeric Brun0655c9b2019-10-17 16:45:56 +0200619 if (((code & (ERR_WARN|ERR_ALERT)) == ERR_WARN))
620 ha_warning("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
621 else
622 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100623 }
624 else
625 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
626 file, linenum, args[0], args[1], args[cur_arg]);
627 if (code & ERR_FATAL) {
628 free(err);
629 cur_arg += 1 + kw->skip;
630 goto out;
631 }
632 }
633 free(err);
634 cur_arg += 1 + kw->skip;
635 continue;
636 }
637
638 err = NULL;
639 if (!bind_dumped) {
640 bind_dump_kws(&err);
641 indent_msg(&err, 4);
642 bind_dumped = 1;
643 }
644
645 ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
646 file, linenum, args[0], args[1], args[cur_arg],
647 err ? " Registered keywords :" : "", err ? err : "");
648 free(err);
649
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 goto out;
654 }
655 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
656 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
657 ha_alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
658 file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
663 err_code |= ERR_WARN;
664
665 /* flush useless bits */
666 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
667 goto out;
668 }
669 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
670 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
671 err_code |= ERR_WARN;
672
673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
675
676 if (!*args[1]) {
677 ha_alert("parsing [%s:%d] : '%s' expects an URI.\n",
678 file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682
683 free(curproxy->monitor_uri);
684 curproxy->monitor_uri_len = strlen(args[1]);
685 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
686 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
687 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
688
689 goto out;
690 }
691 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
692 if (alertif_too_many_args(1, file, linenum, args, &err_code))
693 goto out;
694
695 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
696 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
697 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
698 else {
699 ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703 }
704 else if (!strcmp(args[0], "id")) {
705 struct eb32_node *node;
706
707 if (curproxy == &defproxy) {
708 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713
714 if (alertif_too_many_args(1, file, linenum, args, &err_code))
715 goto out;
716
717 if (!*args[1]) {
718 ha_alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723
724 curproxy->uuid = atol(args[1]);
725 curproxy->conf.id.key = curproxy->uuid;
726 curproxy->options |= PR_O_FORCED_ID;
727
728 if (curproxy->uuid <= 0) {
729 ha_alert("parsing [%s:%d]: custom id has to be > 0.\n",
730 file, linenum);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
736 if (node) {
737 struct proxy *target = container_of(node, struct proxy, conf.id);
738 ha_alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
739 file, linenum, proxy_type_str(curproxy), curproxy->id,
740 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 eb32_insert(&used_proxy_id, &curproxy->conf.id);
745 }
746 else if (!strcmp(args[0], "description")) {
747 int i, len=0;
748 char *d;
749
750 if (curproxy == &defproxy) {
751 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 if (!*args[1]) {
758 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
759 file, linenum, args[0]);
760 return -1;
761 }
762
763 for (i = 1; *args[i]; i++)
764 len += strlen(args[i]) + 1;
765
766 d = calloc(1, len);
767 curproxy->desc = d;
768
769 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
770 for (i = 2; *args[i]; i++)
771 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
772
773 }
774 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
775 if (alertif_too_many_args(0, file, linenum, args, &err_code))
776 goto out;
777 curproxy->state = PR_STSTOPPED;
778 }
779 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
780 if (alertif_too_many_args(0, file, linenum, args, &err_code))
781 goto out;
782 curproxy->state = PR_STNEW;
783 }
784 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
785 int cur_arg = 1;
786 unsigned long set = 0;
787
788 while (*args[cur_arg]) {
789 if (strcmp(args[cur_arg], "all") == 0) {
790 set = 0;
791 break;
792 }
Willy Tarreauff9c9142019-02-07 10:39:36 +0100793 if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, &errmsg)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100794 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 cur_arg++;
799 }
800 curproxy->bind_proc = set;
801 }
802 else if (!strcmp(args[0], "acl")) { /* add an ACL */
803 if (curproxy == &defproxy) {
804 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808
809 err = invalid_char(args[1]);
810 if (err) {
811 ha_alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
812 file, linenum, *err, args[1]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100817 if (strcasecmp(args[1], "or") == 0) {
Tim Duesterhusf1bc24c2020-02-06 22:04:03 +0100818 ha_alert("parsing [%s:%d] : acl name '%s' will never match. 'or' is used to express a "
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100819 "logical disjunction within a condition.\n",
820 file, linenum, args[1]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100825 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
826 ha_alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
827 file, linenum, args[1], errmsg);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 }
832 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
833
834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
835 err_code |= ERR_WARN;
836
837 if (*(args[1]) == 0) {
838 ha_alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
839 file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 free(curproxy->dyncookie_key);
844 curproxy->dyncookie_key = strdup(args[1]);
845 }
846 else if (!strcmp(args[0], "cookie")) { /* cookie name */
847 int cur_arg;
848
849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
850 err_code |= ERR_WARN;
851
852 if (*(args[1]) == 0) {
853 ha_alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
854 file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858
859 curproxy->ck_opts = 0;
860 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
861 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
862 free(curproxy->cookie_name);
863 curproxy->cookie_name = strdup(args[1]);
864 curproxy->cookie_len = strlen(curproxy->cookie_name);
865
866 cur_arg = 2;
867 while (*(args[cur_arg])) {
868 if (!strcmp(args[cur_arg], "rewrite")) {
869 curproxy->ck_opts |= PR_CK_RW;
870 }
871 else if (!strcmp(args[cur_arg], "indirect")) {
872 curproxy->ck_opts |= PR_CK_IND;
873 }
874 else if (!strcmp(args[cur_arg], "insert")) {
875 curproxy->ck_opts |= PR_CK_INS;
876 }
877 else if (!strcmp(args[cur_arg], "nocache")) {
878 curproxy->ck_opts |= PR_CK_NOC;
879 }
880 else if (!strcmp(args[cur_arg], "postonly")) {
881 curproxy->ck_opts |= PR_CK_POST;
882 }
883 else if (!strcmp(args[cur_arg], "preserve")) {
884 curproxy->ck_opts |= PR_CK_PSV;
885 }
886 else if (!strcmp(args[cur_arg], "prefix")) {
887 curproxy->ck_opts |= PR_CK_PFX;
888 }
889 else if (!strcmp(args[cur_arg], "httponly")) {
890 curproxy->ck_opts |= PR_CK_HTTPONLY;
891 }
892 else if (!strcmp(args[cur_arg], "secure")) {
893 curproxy->ck_opts |= PR_CK_SECURE;
894 }
895 else if (!strcmp(args[cur_arg], "domain")) {
896 if (!*args[cur_arg + 1]) {
897 ha_alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
898 file, linenum, args[cur_arg]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902
Joao Moraise1583752019-10-30 21:04:00 -0300903 if (!strchr(args[cur_arg + 1], '.')) {
904 /* rfc6265, 5.2.3 The Domain Attribute */
905 ha_warning("parsing [%s:%d]: domain '%s' contains no embedded dot,"
906 " this configuration may not work properly (see RFC6265#5.2.3).\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100907 file, linenum, args[cur_arg + 1]);
908 err_code |= ERR_WARN;
909 }
910
911 err = invalid_domainchar(args[cur_arg + 1]);
912 if (err) {
913 ha_alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
914 file, linenum, *err, args[cur_arg + 1]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918
919 if (!curproxy->cookie_domain) {
920 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
921 } else {
922 /* one domain was already specified, add another one by
923 * building the string which will be returned along with
924 * the cookie.
925 */
926 char *new_ptr;
927 int new_len = strlen(curproxy->cookie_domain) +
928 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
929 new_ptr = malloc(new_len);
930 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
931 free(curproxy->cookie_domain);
932 curproxy->cookie_domain = new_ptr;
933 }
934 cur_arg++;
935 }
936 else if (!strcmp(args[cur_arg], "maxidle")) {
937 unsigned int maxidle;
938 const char *res;
939
940 if (!*args[cur_arg + 1]) {
941 ha_alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
942 file, linenum, args[cur_arg]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946
947 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200948 if (res == PARSE_TIME_OVER) {
949 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
950 file, linenum, args[cur_arg+1], args[cur_arg]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 else if (res == PARSE_TIME_UNDER) {
955 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
956 file, linenum, args[cur_arg+1], args[cur_arg]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100961 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
962 file, linenum, *res, args[cur_arg]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 curproxy->cookie_maxidle = maxidle;
967 cur_arg++;
968 }
969 else if (!strcmp(args[cur_arg], "maxlife")) {
970 unsigned int maxlife;
971 const char *res;
972
973 if (!*args[cur_arg + 1]) {
974 ha_alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
975 file, linenum, args[cur_arg]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
Willy Tarreau9faebe32019-06-07 19:00:37 +0200980
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100981 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200982 if (res == PARSE_TIME_OVER) {
983 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
984 file, linenum, args[cur_arg+1], args[cur_arg]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 else if (res == PARSE_TIME_UNDER) {
989 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
990 file, linenum, args[cur_arg+1], args[cur_arg]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100995 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
996 file, linenum, *res, args[cur_arg]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 curproxy->cookie_maxlife = maxlife;
1001 cur_arg++;
1002 }
1003 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
1004
1005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
1006 err_code |= ERR_WARN;
1007 curproxy->ck_opts |= PR_CK_DYNAMIC;
1008 }
Christopher Faulet2f533902020-01-21 11:06:48 +01001009 else if (!strcmp(args[cur_arg], "attr")) {
1010 char *val;
1011 if (!*args[cur_arg + 1]) {
1012 ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
1013 file, linenum, args[cur_arg]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 val = args[cur_arg + 1];
1018 while (*val) {
Willy Tarreau90807112020-02-25 08:16:33 +01001019 if (iscntrl((unsigned char)*val) || *val == ';') {
Christopher Faulet2f533902020-01-21 11:06:48 +01001020 ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
1021 file, linenum, *val);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025 val++;
1026 }
1027 /* don't add ';' for the first attribute */
1028 if (!curproxy->cookie_attrs)
1029 curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
1030 else
1031 memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
1032 cur_arg++;
1033 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001034
1035 else {
Christopher Faulet2f533902020-01-21 11:06:48 +01001036 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 +01001037 file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 cur_arg++;
1042 }
1043 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
1044 ha_alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1045 file, linenum);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 }
1048
1049 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
1050 ha_alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1051 file, linenum);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 }
1054
1055 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
1056 ha_alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
1057 file, linenum);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 }
1060 }/* end else if (!strcmp(args[0], "cookie")) */
1061 else if (!strcmp(args[0], "email-alert")) {
1062 if (*(args[1]) == 0) {
1063 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1064 file, linenum, args[0]);
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067 }
1068
1069 if (!strcmp(args[1], "from")) {
1070 if (*(args[1]) == 0) {
1071 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1072 file, linenum, args[1]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 free(curproxy->email_alert.from);
1077 curproxy->email_alert.from = strdup(args[2]);
1078 }
1079 else if (!strcmp(args[1], "mailers")) {
1080 if (*(args[1]) == 0) {
1081 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1082 file, linenum, args[1]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 free(curproxy->email_alert.mailers.name);
1087 curproxy->email_alert.mailers.name = strdup(args[2]);
1088 }
1089 else if (!strcmp(args[1], "myhostname")) {
1090 if (*(args[1]) == 0) {
1091 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1092 file, linenum, args[1]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 free(curproxy->email_alert.myhostname);
1097 curproxy->email_alert.myhostname = strdup(args[2]);
1098 }
1099 else if (!strcmp(args[1], "level")) {
1100 curproxy->email_alert.level = get_log_level(args[2]);
1101 if (curproxy->email_alert.level < 0) {
1102 ha_alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
1103 file, linenum, args[1], args[2]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107 }
1108 else if (!strcmp(args[1], "to")) {
1109 if (*(args[1]) == 0) {
1110 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1111 file, linenum, args[1]);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
1114 }
1115 free(curproxy->email_alert.to);
1116 curproxy->email_alert.to = strdup(args[2]);
1117 }
1118 else {
1119 ha_alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
1120 file, linenum, args[1]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123 }
1124 /* Indicate that the email_alert is at least partially configured */
1125 curproxy->email_alert.set = 1;
1126 }/* end else if (!strcmp(args[0], "email-alert")) */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001127 else if (!strcmp(args[0], "persist")) { /* persist */
1128 if (*(args[1]) == 0) {
1129 ha_alert("parsing [%s:%d] : missing persist method.\n",
1130 file, linenum);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
1134
1135 if (!strncmp(args[1], "rdp-cookie", 10)) {
1136 curproxy->options2 |= PR_O2_RDPC_PRST;
1137
1138 if (*(args[1] + 10) == '(') { /* cookie name */
1139 const char *beg, *end;
1140
1141 beg = args[1] + 11;
1142 end = strchr(beg, ')');
1143
1144 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1145 goto out;
1146
1147 if (!end || end == beg) {
1148 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1149 file, linenum);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
1153
1154 free(curproxy->rdp_cookie_name);
1155 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1156 curproxy->rdp_cookie_len = end-beg;
1157 }
1158 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
1159 free(curproxy->rdp_cookie_name);
1160 curproxy->rdp_cookie_name = strdup("msts");
1161 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1162 }
1163 else { /* syntax */
1164 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1165 file, linenum);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
1169 }
1170 else {
1171 ha_alert("parsing [%s:%d] : unknown persist method.\n",
1172 file, linenum);
1173 err_code |= ERR_ALERT | ERR_FATAL;
1174 goto out;
1175 }
1176 }
1177 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Tim Duesterhus473c2832019-05-06 01:19:52 +02001178 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 +01001179 err_code |= ERR_ALERT | ERR_FATAL;
1180 goto out;
1181 }
1182 else if (!strcmp(args[0], "load-server-state-from-file")) {
1183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1184 err_code |= ERR_WARN;
1185 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
1186 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
1187 }
1188 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
1189 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
1190 }
1191 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
1192 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
1193 }
1194 else {
1195 ha_alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
1196 file, linenum, args[0], args[1]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 }
1201 else if (!strcmp(args[0], "server-state-file-name")) {
1202 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1203 err_code |= ERR_WARN;
1204 if (*(args[1]) == 0) {
1205 ha_alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
1206 file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209 }
1210 else if (!strcmp(args[1], "use-backend-name"))
1211 curproxy->server_state_file_name = strdup(curproxy->id);
1212 else
1213 curproxy->server_state_file_name = strdup(args[1]);
1214 }
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +01001215 else if (!strcmp(args[0], "max-session-srv-conns")) {
1216 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1217 err_code |= ERR_WARN;
1218 if (*(args[1]) == 0) {
1219 ha_alert("parsine [%s:%d] : '%s' expects a number. Got no argument\n",
1220 file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 curproxy->max_out_conns = atoi(args[1]);
1225 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001226 else if (!strcmp(args[0], "capture")) {
1227 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1228 err_code |= ERR_WARN;
1229
1230 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1231 if (curproxy == &defproxy) {
1232 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236
1237 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1238 goto out;
1239
1240 if (*(args[4]) == 0) {
1241 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246 free(curproxy->capture_name);
1247 curproxy->capture_name = strdup(args[2]);
1248 curproxy->capture_namelen = strlen(curproxy->capture_name);
1249 curproxy->capture_len = atol(args[4]);
1250 curproxy->to_log |= LW_COOKIE;
1251 }
1252 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1253 struct cap_hdr *hdr;
1254
1255 if (curproxy == &defproxy) {
1256 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
1261 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1262 goto out;
1263
1264 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1265 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1266 file, linenum, args[0], args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 hdr = calloc(1, sizeof(*hdr));
1272 hdr->next = curproxy->req_cap;
1273 hdr->name = strdup(args[3]);
1274 hdr->namelen = strlen(args[3]);
1275 hdr->len = atol(args[5]);
1276 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1277 hdr->index = curproxy->nb_req_cap++;
1278 curproxy->req_cap = hdr;
1279 curproxy->to_log |= LW_REQHDR;
1280 }
1281 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1282 struct cap_hdr *hdr;
1283
1284 if (curproxy == &defproxy) {
1285 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289
1290 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1291 goto out;
1292
1293 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1294 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1295 file, linenum, args[0], args[1]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299 hdr = calloc(1, sizeof(*hdr));
1300 hdr->next = curproxy->rsp_cap;
1301 hdr->name = strdup(args[3]);
1302 hdr->namelen = strlen(args[3]);
1303 hdr->len = atol(args[5]);
1304 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1305 hdr->index = curproxy->nb_rsp_cap++;
1306 curproxy->rsp_cap = hdr;
1307 curproxy->to_log |= LW_RSPHDR;
1308 }
1309 else {
1310 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1311 file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 }
1316 else if (!strcmp(args[0], "retries")) { /* connection retries */
1317 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1318 err_code |= ERR_WARN;
1319
1320 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1321 goto out;
1322
1323 if (*(args[1]) == 0) {
1324 ha_alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1325 file, linenum, args[0]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329 curproxy->conn_retries = atol(args[1]);
1330 }
1331 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1332 struct act_rule *rule;
1333
1334 if (curproxy == &defproxy) {
1335 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1336 err_code |= ERR_ALERT | ERR_FATAL;
1337 goto out;
1338 }
1339
1340 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
1341 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001342 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001343 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1344 file, linenum, args[0]);
1345 err_code |= ERR_WARN;
1346 }
1347
1348 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
1349
1350 if (!rule) {
1351 err_code |= ERR_ALERT | ERR_ABORT;
1352 goto out;
1353 }
1354
1355 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
1356 err_code |= warnif_cond_conflicts(rule->cond,
1357 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1358 file, linenum);
1359
1360 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
1361 }
1362 else if (!strcmp(args[0], "http-response")) { /* response access control */
1363 struct act_rule *rule;
1364
1365 if (curproxy == &defproxy) {
1366 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
1369 }
1370
1371 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
1372 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001373 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001374 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1375 file, linenum, args[0]);
1376 err_code |= ERR_WARN;
1377 }
1378
1379 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
1380
1381 if (!rule) {
1382 err_code |= ERR_ALERT | ERR_ABORT;
1383 goto out;
1384 }
1385
1386 err_code |= warnif_cond_conflicts(rule->cond,
1387 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1388 file, linenum);
1389
1390 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
1391 }
Christopher Faulet6d0c3df2020-01-22 09:26:35 +01001392 else if (!strcmp(args[0], "http-after-response")) {
1393 struct act_rule *rule;
1394
1395 if (curproxy == &defproxy) {
1396 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
1399 }
1400
1401 if (!LIST_ISEMPTY(&curproxy->http_after_res_rules) &&
1402 !LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->cond &&
1403 (LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
1404 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1405 file, linenum, args[0]);
1406 err_code |= ERR_WARN;
1407 }
1408
1409 rule = parse_http_after_res_cond((const char **)args + 1, file, linenum, curproxy);
1410
1411 if (!rule) {
1412 err_code |= ERR_ALERT | ERR_ABORT;
1413 goto out;
1414 }
1415
1416 err_code |= warnif_cond_conflicts(rule->cond,
1417 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1418 file, linenum);
1419
1420 LIST_ADDQ(&curproxy->http_after_res_rules, &rule->list);
1421 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001422 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
1423 /* set the header name and length into the proxy structure */
1424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1425 err_code |= ERR_WARN;
1426
1427 if (!*args[1]) {
1428 ha_alert("parsing [%s:%d] : '%s' requires a header string.\n",
1429 file, linenum, args[0]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001434 /* set the desired header name, in lower case */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001435 free(curproxy->server_id_hdr_name);
1436 curproxy->server_id_hdr_name = strdup(args[1]);
1437 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001438 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 +01001439 }
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001440 else if (!strcmp(args[0], "block")) {
1441 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 +01001442
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001445 }
1446 else if (!strcmp(args[0], "redirect")) {
1447 struct redirect_rule *rule;
1448
1449 if (curproxy == &defproxy) {
1450 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
1454
1455 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
1456 ha_alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
1457 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 goto out;
1460 }
1461
1462 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1463 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
1464 err_code |= warnif_cond_conflicts(rule->cond,
1465 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1466 file, linenum);
1467 }
1468 else if (!strcmp(args[0], "use_backend")) {
1469 struct switching_rule *rule;
1470
1471 if (curproxy == &defproxy) {
1472 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
1475 }
1476
1477 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1478 err_code |= ERR_WARN;
1479
1480 if (*(args[1]) == 0) {
1481 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
1487 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1488 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1489 file, linenum, errmsg);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
1495 }
1496 else if (*args[2]) {
1497 ha_alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
1498 file, linenum, args[2]);
1499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
1501 }
1502
1503 rule = calloc(1, sizeof(*rule));
1504 if (!rule) {
1505 ha_alert("Out of memory error.\n");
1506 goto out;
1507 }
1508 rule->cond = cond;
1509 rule->be.name = strdup(args[1]);
1510 rule->line = linenum;
1511 rule->file = strdup(file);
1512 if (!rule->file) {
1513 ha_alert("Out of memory error.\n");
1514 goto out;
1515 }
1516 LIST_INIT(&rule->list);
1517 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1518 }
1519 else if (strcmp(args[0], "use-server") == 0) {
1520 struct server_rule *rule;
1521
1522 if (curproxy == &defproxy) {
1523 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1524 err_code |= ERR_ALERT | ERR_FATAL;
1525 goto out;
1526 }
1527
1528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1529 err_code |= ERR_WARN;
1530
1531 if (*(args[1]) == 0) {
1532 ha_alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
1533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
1535 }
1536
1537 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1538 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1539 file, linenum, args[0]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542 }
1543
1544 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1545 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1546 file, linenum, errmsg);
1547 err_code |= ERR_ALERT | ERR_FATAL;
1548 goto out;
1549 }
1550
1551 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1552
1553 rule = calloc(1, sizeof(*rule));
1554 rule->cond = cond;
1555 rule->srv.name = strdup(args[1]);
Jerome Magnin824186b2020-03-29 09:37:12 +02001556 rule->line = linenum;
1557 rule->file = strdup(file);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001558 LIST_INIT(&rule->list);
1559 LIST_ADDQ(&curproxy->server_rules, &rule->list);
1560 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
1561 }
1562 else if ((!strcmp(args[0], "force-persist")) ||
1563 (!strcmp(args[0], "ignore-persist"))) {
1564 struct persist_rule *rule;
1565
1566 if (curproxy == &defproxy) {
1567 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 goto out;
1570 }
1571
1572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1573 err_code |= ERR_WARN;
1574
1575 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
1576 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1577 file, linenum, args[0]);
1578 err_code |= ERR_ALERT | ERR_FATAL;
1579 goto out;
1580 }
1581
1582 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
1583 ha_alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
1584 file, linenum, args[0], errmsg);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
1589 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
1590 * where force-persist is applied.
1591 */
1592 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
1593
1594 rule = calloc(1, sizeof(*rule));
1595 rule->cond = cond;
1596 if (!strcmp(args[0], "force-persist")) {
1597 rule->type = PERSIST_TYPE_FORCE;
1598 } else {
1599 rule->type = PERSIST_TYPE_IGNORE;
1600 }
1601 LIST_INIT(&rule->list);
1602 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
1603 }
1604 else if (!strcmp(args[0], "stick-table")) {
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001605 struct stktable *other;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001606
1607 if (curproxy == &defproxy) {
1608 ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
1609 file, linenum);
1610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
1612 }
1613
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001614 other = stktable_find_by_name(curproxy->id);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001615 if (other) {
1616 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 +01001617 file, linenum, curproxy->id,
1618 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
1619 other->proxy ? other->id : other->peers.p->id,
1620 other->conf.file, other->conf.line);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001625 curproxy->table = calloc(1, sizeof *curproxy->table);
1626 if (!curproxy->table) {
1627 ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
1628 file, linenum, args[0], args[1]);
1629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
1631 }
1632
Frédéric Lécaillec02766a2019-03-20 15:06:55 +01001633 err_code |= parse_stick_table(file, linenum, args, curproxy->table,
1634 curproxy->id, curproxy->id, NULL);
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001635 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001636 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001637
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001638 /* Store the proxy in the stick-table. */
1639 curproxy->table->proxy = curproxy;
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001640
1641 stktable_store_name(curproxy->table);
1642 curproxy->table->next = stktables_list;
1643 stktables_list = curproxy->table;
Frédéric Lécaille015e4d72019-03-19 14:55:01 +01001644
1645 /* Add this proxy to the list of proxies which refer to its stick-table. */
1646 if (curproxy->table->proxies_list != curproxy) {
1647 curproxy->next_stkt_ref = curproxy->table->proxies_list;
1648 curproxy->table->proxies_list = curproxy;
1649 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001650 }
1651 else if (!strcmp(args[0], "stick")) {
1652 struct sticking_rule *rule;
1653 struct sample_expr *expr;
1654 int myidx = 0;
1655 const char *name = NULL;
1656 int flags;
1657
1658 if (curproxy == &defproxy) {
1659 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663
1664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
1665 err_code |= ERR_WARN;
1666 goto out;
1667 }
1668
1669 myidx++;
1670 if ((strcmp(args[myidx], "store") == 0) ||
1671 (strcmp(args[myidx], "store-request") == 0)) {
1672 myidx++;
1673 flags = STK_IS_STORE;
1674 }
1675 else if (strcmp(args[myidx], "store-response") == 0) {
1676 myidx++;
1677 flags = STK_IS_STORE | STK_ON_RSP;
1678 }
1679 else if (strcmp(args[myidx], "match") == 0) {
1680 myidx++;
1681 flags = STK_IS_MATCH;
1682 }
1683 else if (strcmp(args[myidx], "on") == 0) {
1684 myidx++;
1685 flags = STK_IS_MATCH | STK_IS_STORE;
1686 }
1687 else {
1688 ha_alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
1689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
1691 }
1692
1693 if (*(args[myidx]) == 0) {
1694 ha_alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
1695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
1699 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreaue3b57bf2020-02-14 16:50:14 +01001700 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001701 if (!expr) {
1702 ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
1706
1707 if (flags & STK_ON_RSP) {
1708 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
1709 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
1710 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1711 err_code |= ERR_ALERT | ERR_FATAL;
1712 free(expr);
1713 goto out;
1714 }
1715 } else {
1716 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
1717 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
1718 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 free(expr);
1721 goto out;
1722 }
1723 }
1724
Christopher Faulet711ed6a2019-07-16 14:16:10 +02001725 /* check if we need to allocate an http_txn struct for HTTP parsing */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001726 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
1727
1728 if (strcmp(args[myidx], "table") == 0) {
1729 myidx++;
1730 name = args[myidx++];
1731 }
1732
1733 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
1734 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
1735 ha_alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
1736 file, linenum, args[0], errmsg);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 free(expr);
1739 goto out;
1740 }
1741 }
1742 else if (*(args[myidx])) {
1743 ha_alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
1744 file, linenum, args[0], args[myidx]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 free(expr);
1747 goto out;
1748 }
1749 if (flags & STK_ON_RSP)
1750 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
1751 else
1752 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1753
1754 rule = calloc(1, sizeof(*rule));
1755 rule->cond = cond;
1756 rule->expr = expr;
1757 rule->flags = flags;
1758 rule->table.name = name ? strdup(name) : NULL;
1759 LIST_INIT(&rule->list);
1760 if (flags & STK_ON_RSP)
1761 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
1762 else
1763 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
1764 }
1765 else if (!strcmp(args[0], "stats")) {
1766 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1767 curproxy->uri_auth = NULL; /* we must detach from the default config */
1768
1769 if (!*args[1]) {
1770 goto stats_error_parsing;
1771 } else if (!strcmp(args[1], "admin")) {
1772 struct stats_admin_rule *rule;
1773
1774 if (curproxy == &defproxy) {
1775 ha_alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
1778 }
1779
1780 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1781 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1782 err_code |= ERR_ALERT | ERR_ABORT;
1783 goto out;
1784 }
1785
1786 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1787 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1788 file, linenum, args[0], args[1]);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1793 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
1794 file, linenum, args[0], args[1], errmsg);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
1797 }
1798
1799 err_code |= warnif_cond_conflicts(cond,
1800 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1801 file, linenum);
1802
1803 rule = calloc(1, sizeof(*rule));
1804 rule->cond = cond;
1805 LIST_INIT(&rule->list);
1806 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
1807 } else if (!strcmp(args[1], "uri")) {
1808 if (*(args[2]) == 0) {
1809 ha_alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1813 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1814 err_code |= ERR_ALERT | ERR_ABORT;
1815 goto out;
1816 }
1817 } else if (!strcmp(args[1], "realm")) {
1818 if (*(args[2]) == 0) {
1819 ha_alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
1822 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1823 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1824 err_code |= ERR_ALERT | ERR_ABORT;
1825 goto out;
1826 }
1827 } else if (!strcmp(args[1], "refresh")) {
1828 unsigned interval;
1829
1830 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02001831 if (err == PARSE_TIME_OVER) {
1832 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to stats refresh interval, maximum value is 2147483647 s (~68 years).\n",
1833 file, linenum, args[2]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837 else if (err == PARSE_TIME_UNDER) {
1838 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to stats refresh interval, minimum non-null value is 1 s.\n",
1839 file, linenum, args[2]);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843 else if (err) {
1844 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to stats refresh interval.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001845 file, linenum, *err);
1846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
1848 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1849 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1850 err_code |= ERR_ALERT | ERR_ABORT;
1851 goto out;
1852 }
1853 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
1854 struct act_rule *rule;
1855
1856 if (curproxy == &defproxy) {
1857 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861
1862 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1863 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1864 err_code |= ERR_ALERT | ERR_ABORT;
1865 goto out;
1866 }
1867
1868 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
1869 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
1870 ha_warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1871 file, linenum, args[0]);
1872 err_code |= ERR_WARN;
1873 }
1874
1875 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
1876
1877 if (!rule) {
1878 err_code |= ERR_ALERT | ERR_ABORT;
1879 goto out;
1880 }
1881
1882 err_code |= warnif_cond_conflicts(rule->cond,
1883 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1884 file, linenum);
1885 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
1886
1887 } else if (!strcmp(args[1], "auth")) {
1888 if (*(args[2]) == 0) {
1889 ha_alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1893 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1894 err_code |= ERR_ALERT | ERR_ABORT;
1895 goto out;
1896 }
1897 } else if (!strcmp(args[1], "scope")) {
1898 if (*(args[2]) == 0) {
1899 ha_alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1900 err_code |= ERR_ALERT | ERR_FATAL;
1901 goto out;
1902 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1903 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1904 err_code |= ERR_ALERT | ERR_ABORT;
1905 goto out;
1906 }
1907 } else if (!strcmp(args[1], "enable")) {
1908 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1909 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1910 err_code |= ERR_ALERT | ERR_ABORT;
1911 goto out;
1912 }
1913 } else if (!strcmp(args[1], "hide-version")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001914 if (!stats_set_flag(&curproxy->uri_auth, STAT_HIDEVER)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001915 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1916 err_code |= ERR_ALERT | ERR_ABORT;
1917 goto out;
1918 }
1919 } else if (!strcmp(args[1], "show-legends")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001920 if (!stats_set_flag(&curproxy->uri_auth, STAT_SHLGNDS)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001921 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1922 err_code |= ERR_ALERT | ERR_ABORT;
1923 goto out;
1924 }
1925 } else if (!strcmp(args[1], "show-node")) {
1926
1927 if (*args[2]) {
1928 int i;
1929 char c;
1930
1931 for (i=0; args[2][i]; i++) {
1932 c = args[2][i];
1933 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1934 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
1935 break;
1936 }
1937
1938 if (!i || args[2][i]) {
1939 ha_alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1940 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1941 file, linenum, args[0], args[1]);
1942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
1944 }
1945 }
1946
1947 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1948 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1949 err_code |= ERR_ALERT | ERR_ABORT;
1950 goto out;
1951 }
1952 } else if (!strcmp(args[1], "show-desc")) {
1953 char *desc = NULL;
1954
1955 if (*args[2]) {
1956 int i, len=0;
1957 char *d;
1958
1959 for (i = 2; *args[i]; i++)
1960 len += strlen(args[i]) + 1;
1961
1962 desc = d = calloc(1, len);
1963
1964 d += snprintf(d, desc + len - d, "%s", args[2]);
1965 for (i = 3; *args[i]; i++)
1966 d += snprintf(d, desc + len - d, " %s", args[i]);
1967 }
1968
1969 if (!*args[2] && !global.desc)
1970 ha_warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1971 file, linenum, args[1]);
1972 else {
1973 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
1974 free(desc);
1975 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1976 err_code |= ERR_ALERT | ERR_ABORT;
1977 goto out;
1978 }
1979 free(desc);
1980 }
1981 } else {
1982stats_error_parsing:
1983 ha_alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
1984 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
1985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
1987 }
1988 }
1989 else if (!strcmp(args[0], "option")) {
1990 int optnum;
1991
1992 if (*(args[1]) == '\0') {
1993 ha_alert("parsing [%s:%d]: '%s' expects an option name.\n",
1994 file, linenum, args[0]);
1995 err_code |= ERR_ALERT | ERR_FATAL;
1996 goto out;
1997 }
1998
1999 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2000 if (!strcmp(args[1], cfg_opts[optnum].name)) {
2001 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
2002 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2003 file, linenum, cfg_opts[optnum].name);
2004 err_code |= ERR_ALERT | ERR_FATAL;
2005 goto out;
2006 }
2007 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2008 goto out;
2009
2010 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2011 err_code |= ERR_WARN;
2012 goto out;
2013 }
2014
2015 curproxy->no_options &= ~cfg_opts[optnum].val;
2016 curproxy->options &= ~cfg_opts[optnum].val;
2017
2018 switch (kwm) {
2019 case KWM_STD:
2020 curproxy->options |= cfg_opts[optnum].val;
2021 break;
2022 case KWM_NO:
2023 curproxy->no_options |= cfg_opts[optnum].val;
2024 break;
2025 case KWM_DEF: /* already cleared */
2026 break;
2027 }
2028
2029 goto out;
2030 }
2031 }
2032
2033 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2034 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
2035 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
2036 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2037 file, linenum, cfg_opts2[optnum].name);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2042 goto out;
2043 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2044 err_code |= ERR_WARN;
2045 goto out;
2046 }
2047
Christopher Faulet31930372019-07-15 10:16:58 +02002048 /* "[no] option http-use-htx" is deprecated */
2049 if (!strcmp(cfg_opts2[optnum].name, "http-use-htx")) {
Christopher Fauletf89f0992019-07-19 11:17:38 +02002050 if (kwm ==KWM_NO) {
2051 ha_warning("parsing [%s:%d]: option '%s' is deprecated and ignored."
2052 " The HTX mode is now the only supported mode.\n",
2053 file, linenum, cfg_opts2[optnum].name);
2054 err_code |= ERR_WARN;
2055 }
Christopher Faulet31930372019-07-15 10:16:58 +02002056 goto out;
2057 }
2058
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002059 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2060 curproxy->options2 &= ~cfg_opts2[optnum].val;
2061
2062 switch (kwm) {
2063 case KWM_STD:
2064 curproxy->options2 |= cfg_opts2[optnum].val;
2065 break;
2066 case KWM_NO:
2067 curproxy->no_options2 |= cfg_opts2[optnum].val;
2068 break;
2069 case KWM_DEF: /* already cleared */
2070 break;
2071 }
2072 goto out;
2073 }
2074 }
2075
2076 /* HTTP options override each other. They can be cancelled using
2077 * "no option xxx" which only switches to default mode if the mode
2078 * was this one (useful for cancelling options set in defaults
2079 * sections).
2080 */
2081 if (strcmp(args[1], "httpclose") == 0 || strcmp(args[1], "forceclose") == 0) {
Tim Duesterhus10c6c162019-05-14 20:58:00 +02002082 if (strcmp(args[1], "forceclose") == 0) {
2083 if (!already_warned(WARN_FORCECLOSE_DEPRECATED))
2084 ha_warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'httpclose', and will not be supported by future versions.\n",
2085 file, linenum, args[1]);
2086 err_code |= ERR_WARN;
2087 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002088 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2089 goto out;
2090 if (kwm == KWM_STD) {
2091 curproxy->options &= ~PR_O_HTTP_MODE;
2092 curproxy->options |= PR_O_HTTP_CLO;
2093 goto out;
2094 }
2095 else if (kwm == KWM_NO) {
2096 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO)
2097 curproxy->options &= ~PR_O_HTTP_MODE;
2098 goto out;
2099 }
2100 }
2101 else if (strcmp(args[1], "http-server-close") == 0) {
2102 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2103 goto out;
2104 if (kwm == KWM_STD) {
2105 curproxy->options &= ~PR_O_HTTP_MODE;
2106 curproxy->options |= PR_O_HTTP_SCL;
2107 goto out;
2108 }
2109 else if (kwm == KWM_NO) {
2110 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
2111 curproxy->options &= ~PR_O_HTTP_MODE;
2112 goto out;
2113 }
2114 }
2115 else if (strcmp(args[1], "http-keep-alive") == 0) {
2116 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2117 goto out;
2118 if (kwm == KWM_STD) {
2119 curproxy->options &= ~PR_O_HTTP_MODE;
2120 curproxy->options |= PR_O_HTTP_KAL;
2121 goto out;
2122 }
2123 else if (kwm == KWM_NO) {
2124 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
2125 curproxy->options &= ~PR_O_HTTP_MODE;
2126 goto out;
2127 }
2128 }
2129 else if (strcmp(args[1], "http-tunnel") == 0) {
Christopher Faulet73e8ede2019-07-16 15:04:46 +02002130 ha_warning("parsing [%s:%d]: the option '%s' is deprecated and will be removed in next version.\n",
2131 file, linenum, args[1]);
2132 err_code |= ERR_WARN;
2133 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002134 }
2135
2136 /* Redispatch can take an integer argument that control when the
2137 * resispatch occurs. All values are relative to the retries option.
2138 * This can be cancelled using "no option xxx".
2139 */
2140 if (strcmp(args[1], "redispatch") == 0) {
2141 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
2142 err_code |= ERR_WARN;
2143 goto out;
2144 }
2145
2146 curproxy->no_options &= ~PR_O_REDISP;
2147 curproxy->options &= ~PR_O_REDISP;
2148
2149 switch (kwm) {
2150 case KWM_STD:
2151 curproxy->options |= PR_O_REDISP;
2152 curproxy->redispatch_after = -1;
2153 if(*args[2]) {
2154 curproxy->redispatch_after = atol(args[2]);
2155 }
2156 break;
2157 case KWM_NO:
2158 curproxy->no_options |= PR_O_REDISP;
2159 curproxy->redispatch_after = 0;
2160 break;
2161 case KWM_DEF: /* already cleared */
2162 break;
2163 }
2164 goto out;
2165 }
2166
2167 if (kwm != KWM_STD) {
2168 ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
2169 file, linenum, args[1]);
2170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
2172 }
2173
2174 if (!strcmp(args[1], "httplog")) {
2175 char *logformat;
2176 /* generate a complete HTTP log */
2177 logformat = default_http_log_format;
2178 if (*(args[2]) != '\0') {
2179 if (!strcmp(args[2], "clf")) {
2180 curproxy->options2 |= PR_O2_CLFLOG;
2181 logformat = clf_http_log_format;
2182 } else {
2183 ha_alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
2188 goto out;
2189 }
2190 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2191 char *oldlogformat = "log-format";
2192 char *clflogformat = "";
2193
2194 if (curproxy->conf.logformat_string == default_http_log_format)
2195 oldlogformat = "option httplog";
2196 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2197 oldlogformat = "option tcplog";
2198 else if (curproxy->conf.logformat_string == clf_http_log_format)
2199 oldlogformat = "option httplog clf";
2200 if (logformat == clf_http_log_format)
2201 clflogformat = " clf";
2202 ha_warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
2203 file, linenum, clflogformat, oldlogformat);
2204 }
2205 if (curproxy->conf.logformat_string != default_http_log_format &&
2206 curproxy->conf.logformat_string != default_tcp_log_format &&
2207 curproxy->conf.logformat_string != clf_http_log_format)
2208 free(curproxy->conf.logformat_string);
2209 curproxy->conf.logformat_string = logformat;
2210
2211 free(curproxy->conf.lfs_file);
2212 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2213 curproxy->conf.lfs_line = curproxy->conf.args.line;
2214
2215 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2216 ha_warning("parsing [%s:%d] : backend '%s' : 'option httplog' directive is ignored in backends.\n",
2217 file, linenum, curproxy->id);
2218 err_code |= ERR_WARN;
2219 }
2220 }
2221 else if (!strcmp(args[1], "tcplog")) {
2222 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2223 char *oldlogformat = "log-format";
2224
2225 if (curproxy->conf.logformat_string == default_http_log_format)
2226 oldlogformat = "option httplog";
2227 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2228 oldlogformat = "option tcplog";
2229 else if (curproxy->conf.logformat_string == clf_http_log_format)
2230 oldlogformat = "option httplog clf";
2231 ha_warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
2232 file, linenum, oldlogformat);
2233 }
2234 /* generate a detailed TCP log */
2235 if (curproxy->conf.logformat_string != default_http_log_format &&
2236 curproxy->conf.logformat_string != default_tcp_log_format &&
2237 curproxy->conf.logformat_string != clf_http_log_format)
2238 free(curproxy->conf.logformat_string);
2239 curproxy->conf.logformat_string = default_tcp_log_format;
2240
2241 free(curproxy->conf.lfs_file);
2242 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2243 curproxy->conf.lfs_line = curproxy->conf.args.line;
2244
2245 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2246 goto out;
2247
2248 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2249 ha_warning("parsing [%s:%d] : backend '%s' : 'option tcplog' directive is ignored in backends.\n",
2250 file, linenum, curproxy->id);
2251 err_code |= ERR_WARN;
2252 }
2253 }
2254 else if (!strcmp(args[1], "tcpka")) {
2255 /* enable TCP keep-alives on client and server streams */
2256 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
2257 err_code |= ERR_WARN;
2258
2259 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2260 goto out;
2261
2262 if (curproxy->cap & PR_CAP_FE)
2263 curproxy->options |= PR_O_TCP_CLI_KA;
2264 if (curproxy->cap & PR_CAP_BE)
2265 curproxy->options |= PR_O_TCP_SRV_KA;
2266 }
2267 else if (!strcmp(args[1], "httpchk")) {
Christopher Faulet6c2a7432020-04-09 14:48:48 +02002268 err_code |= proxy_parse_httpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2269 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002270 goto out;
2271 }
2272 else if (!strcmp(args[1], "ssl-hello-chk")) {
Christopher Faulet811f78c2020-04-01 11:10:27 +02002273 err_code |= proxy_parse_ssl_hello_chk_opt(args, 0, curproxy, &defproxy, file, linenum);
2274 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002275 goto out;
2276 }
2277 else if (!strcmp(args[1], "smtpchk")) {
Christopher Fauletfbcc77c2020-04-01 20:54:05 +02002278 err_code |= proxy_parse_smtpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2279 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002280 goto out;
2281 }
2282 else if (!strcmp(args[1], "pgsql-check")) {
Christopher Fauletce355072020-04-02 11:44:39 +02002283 err_code |= proxy_parse_pgsql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2284 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002285 goto out;
2286 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002287 else if (!strcmp(args[1], "redis-check")) {
Christopher Faulet33f05df2020-04-01 11:08:50 +02002288 err_code |= proxy_parse_redis_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2289 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002290 goto out;
2291 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002292 else if (!strcmp(args[1], "mysql-check")) {
Christopher Fauletf2b3be52020-04-02 18:07:37 +02002293 err_code |= proxy_parse_mysql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2294 if (err_code & ERR_FATAL)
2295 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002296 }
2297 else if (!strcmp(args[1], "ldap-check")) {
Christopher Faulet1997eca2020-04-03 23:13:50 +02002298 err_code |= proxy_parse_ldap_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2299 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002300 goto out;
2301 }
2302 else if (!strcmp(args[1], "spop-check")) {
Christopher Faulet267b01b2020-04-04 10:27:09 +02002303 err_code |= proxy_parse_spop_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2304 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002305 goto out;
2306 }
2307 else if (!strcmp(args[1], "tcp-check")) {
Christopher Faulet430e4802020-04-09 15:28:16 +02002308 err_code |= proxy_parse_tcp_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2309 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002310 goto out;
2311 }
2312 else if (!strcmp(args[1], "external-check")) {
Christopher Faulet6f557912020-04-09 15:58:50 +02002313 err_code |= proxy_parse_external_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2314 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002315 goto out;
2316 }
2317 else if (!strcmp(args[1], "forwardfor")) {
2318 int cur_arg;
2319
2320 /* insert x-forwarded-for field, but not for the IP address listed as an except.
Christopher Faulet31930372019-07-15 10:16:58 +02002321 * set default options (ie: bitfield, header name, etc)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002322 */
2323
2324 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
2325
2326 free(curproxy->fwdfor_hdr_name);
2327 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2328 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2329
2330 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2331 cur_arg = 2;
2332 while (*(args[cur_arg])) {
2333 if (!strcmp(args[cur_arg], "except")) {
2334 /* suboption except - needs additional argument for it */
2335 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
2336 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2337 file, linenum, args[0], args[1], args[cur_arg]);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
2341 /* flush useless bits */
2342 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
2343 cur_arg += 2;
2344 } else if (!strcmp(args[cur_arg], "header")) {
2345 /* suboption header - needs additional argument for it */
2346 if (*(args[cur_arg+1]) == 0) {
2347 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2348 file, linenum, args[0], args[1], args[cur_arg]);
2349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
2351 }
2352 free(curproxy->fwdfor_hdr_name);
2353 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2354 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2355 cur_arg += 2;
2356 } else if (!strcmp(args[cur_arg], "if-none")) {
2357 curproxy->options &= ~PR_O_FF_ALWAYS;
2358 cur_arg += 1;
2359 } else {
2360 /* unknown suboption - catchall */
2361 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
2362 file, linenum, args[0], args[1]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 } /* end while loop */
2367 }
2368 else if (!strcmp(args[1], "originalto")) {
2369 int cur_arg;
2370
2371 /* insert x-original-to field, but not for the IP address listed as an except.
2372 * set default options (ie: bitfield, header name, etc)
2373 */
2374
2375 curproxy->options |= PR_O_ORGTO;
2376
2377 free(curproxy->orgto_hdr_name);
2378 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2379 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2380
2381 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
2382 cur_arg = 2;
2383 while (*(args[cur_arg])) {
2384 if (!strcmp(args[cur_arg], "except")) {
2385 /* suboption except - needs additional argument for it */
2386 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
2387 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2388 file, linenum, args[0], args[1], args[cur_arg]);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392 /* flush useless bits */
2393 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2394 cur_arg += 2;
2395 } else if (!strcmp(args[cur_arg], "header")) {
2396 /* suboption header - needs additional argument for it */
2397 if (*(args[cur_arg+1]) == 0) {
2398 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2399 file, linenum, args[0], args[1], args[cur_arg]);
2400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
2402 }
2403 free(curproxy->orgto_hdr_name);
2404 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2405 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2406 cur_arg += 2;
2407 } else {
2408 /* unknown suboption - catchall */
2409 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2410 file, linenum, args[0], args[1]);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414 } /* end while loop */
2415 }
2416 else {
2417 ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421 goto out;
2422 }
2423 else if (!strcmp(args[0], "default_backend")) {
2424 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2425 err_code |= ERR_WARN;
2426
2427 if (*(args[1]) == 0) {
2428 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432 free(curproxy->defbe.name);
2433 curproxy->defbe.name = strdup(args[1]);
2434
2435 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
2436 goto out;
2437 }
2438 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002439 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 +01002440
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002443 }
2444 else if (!strcmp(args[0], "http-reuse")) {
2445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2446 err_code |= ERR_WARN;
2447
2448 if (strcmp(args[1], "never") == 0) {
2449 /* enable a graceful server shutdown on an HTTP 404 response */
2450 curproxy->options &= ~PR_O_REUSE_MASK;
2451 curproxy->options |= PR_O_REUSE_NEVR;
2452 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2453 goto out;
2454 }
2455 else if (strcmp(args[1], "safe") == 0) {
2456 /* enable a graceful server shutdown on an HTTP 404 response */
2457 curproxy->options &= ~PR_O_REUSE_MASK;
2458 curproxy->options |= PR_O_REUSE_SAFE;
2459 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2460 goto out;
2461 }
2462 else if (strcmp(args[1], "aggressive") == 0) {
2463 curproxy->options &= ~PR_O_REUSE_MASK;
2464 curproxy->options |= PR_O_REUSE_AGGR;
2465 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2466 goto out;
2467 }
2468 else if (strcmp(args[1], "always") == 0) {
2469 /* enable a graceful server shutdown on an HTTP 404 response */
2470 curproxy->options &= ~PR_O_REUSE_MASK;
2471 curproxy->options |= PR_O_REUSE_ALWS;
2472 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2473 goto out;
2474 }
2475 else {
2476 ha_alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002481 else if (!strcmp(args[0], "monitor")) {
2482 if (curproxy == &defproxy) {
2483 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
2488 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2489 err_code |= ERR_WARN;
2490
2491 if (strcmp(args[1], "fail") == 0) {
2492 /* add a condition to fail monitor requests */
2493 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2494 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2495 file, linenum, args[0], args[1]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499
2500 err_code |= warnif_misplaced_monitor(curproxy, file, linenum, "monitor fail");
2501 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2502 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
2503 file, linenum, args[0], args[1], errmsg);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2508 }
2509 else {
2510 ha_alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 }
Willy Tarreaue5733232019-05-22 19:24:06 +02002515#ifdef USE_TPROXY
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002516 else if (!strcmp(args[0], "transparent")) {
2517 /* enable transparent proxy connections */
2518 curproxy->options |= PR_O_TRANSP;
2519 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2520 goto out;
2521 }
2522#endif
2523 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
2524 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
2525 err_code |= ERR_WARN;
2526
2527 if (*(args[1]) == 0) {
2528 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532 curproxy->maxconn = atol(args[1]);
2533 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2534 goto out;
2535 }
2536 else if (!strcmp(args[0], "backlog")) { /* backlog */
2537 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2538 err_code |= ERR_WARN;
2539
2540 if (*(args[1]) == 0) {
2541 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
2544 }
2545 curproxy->backlog = atol(args[1]);
2546 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2547 goto out;
2548 }
2549 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
2550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
2551 err_code |= ERR_WARN;
2552
2553 if (*(args[1]) == 0) {
2554 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
2558 curproxy->fullconn = atol(args[1]);
2559 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2560 goto out;
2561 }
2562 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2563 if (*(args[1]) == 0) {
2564 ha_alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
2565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
2567 }
2568 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +02002569 if (err == PARSE_TIME_OVER) {
2570 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to grace time, maximum value is 2147483647 ms (~24.8 days).\n",
2571 file, linenum, args[1]);
2572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
2574 }
2575 else if (err == PARSE_TIME_UNDER) {
2576 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to grace time, minimum non-null value is 1 ms.\n",
2577 file, linenum, args[1]);
2578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
2580 }
2581 else if (err) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002582 ha_alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2583 file, linenum, *err);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587 curproxy->grace = val;
2588 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2589 goto out;
2590 }
2591 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2592 struct sockaddr_storage *sk;
2593 int port1, port2;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002594
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
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002603 sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL,
2604 &errmsg, NULL, NULL,
2605 PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002606 if (!sk) {
2607 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
2608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
2610 }
2611
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002612 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2613 goto out;
2614
2615 curproxy->dispatch_addr = *sk;
2616 curproxy->options |= PR_O_DISPATCH;
2617 }
2618 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
2619 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2620 err_code |= ERR_WARN;
2621
2622 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
2623 ha_alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627 }
2628 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2629 /**
2630 * The syntax for hash-type config element is
2631 * hash-type {map-based|consistent} [[<algo>] avalanche]
2632 *
2633 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
2634 */
2635 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
2636
2637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2638 err_code |= ERR_WARN;
2639
2640 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2641 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2642 }
2643 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2644 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2645 }
2646 else if (strcmp(args[1], "avalanche") == 0) {
2647 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]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651 else {
2652 ha_alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656
2657 /* set the hash function to use */
2658 if (!*args[2]) {
2659 /* the default algo is sdbm */
2660 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2661
2662 /* if consistent with no argument, then avalanche modifier is also applied */
2663 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
2664 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2665 } else {
2666 /* set the hash function */
2667 if (!strcmp(args[2], "sdbm")) {
2668 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2669 }
2670 else if (!strcmp(args[2], "djb2")) {
2671 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
2672 }
2673 else if (!strcmp(args[2], "wt6")) {
2674 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
2675 }
2676 else if (!strcmp(args[2], "crc32")) {
2677 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
2678 }
2679 else {
2680 ha_alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
2685 /* set the hash modifier */
2686 if (!strcmp(args[3], "avalanche")) {
2687 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2688 }
2689 else if (*args[3]) {
2690 ha_alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694 }
2695 }
2696 else if (strcmp(args[0], "hash-balance-factor") == 0) {
2697 if (*(args[1]) == 0) {
2698 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
Willy Tarreau76e84f52019-01-14 16:50:58 +01002702 curproxy->lbprm.hash_balance_factor = atol(args[1]);
2703 if (curproxy->lbprm.hash_balance_factor != 0 && curproxy->lbprm.hash_balance_factor <= 100) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002704 ha_alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708 }
2709 else if (strcmp(args[0], "unique-id-format") == 0) {
2710 if (!*(args[1])) {
2711 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715 if (*(args[2])) {
2716 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720 free(curproxy->conf.uniqueid_format_string);
2721 curproxy->conf.uniqueid_format_string = strdup(args[1]);
2722
2723 free(curproxy->conf.uif_file);
2724 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
2725 curproxy->conf.uif_line = curproxy->conf.args.line;
2726 }
2727
2728 else if (strcmp(args[0], "unique-id-header") == 0) {
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002729 char *copy;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002730 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 }
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002735 copy = strdup(args[1]);
2736 if (copy == NULL) {
2737 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741
2742 istfree(&curproxy->header_unique_id);
2743 curproxy->header_unique_id = ist(copy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002744 }
2745
2746 else if (strcmp(args[0], "log-format") == 0) {
2747 if (!*(args[1])) {
2748 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752 if (*(args[2])) {
2753 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2758 char *oldlogformat = "log-format";
2759
2760 if (curproxy->conf.logformat_string == default_http_log_format)
2761 oldlogformat = "option httplog";
2762 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2763 oldlogformat = "option tcplog";
2764 else if (curproxy->conf.logformat_string == clf_http_log_format)
2765 oldlogformat = "option httplog clf";
2766 ha_warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
2767 file, linenum, oldlogformat);
2768 }
2769 if (curproxy->conf.logformat_string != default_http_log_format &&
2770 curproxy->conf.logformat_string != default_tcp_log_format &&
2771 curproxy->conf.logformat_string != clf_http_log_format)
2772 free(curproxy->conf.logformat_string);
2773 curproxy->conf.logformat_string = strdup(args[1]);
2774
2775 free(curproxy->conf.lfs_file);
2776 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2777 curproxy->conf.lfs_line = curproxy->conf.args.line;
2778
2779 /* get a chance to improve log-format error reporting by
2780 * reporting the correct line-number when possible.
2781 */
2782 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2783 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
2784 file, linenum, curproxy->id);
2785 err_code |= ERR_WARN;
2786 }
2787 }
2788 else if (!strcmp(args[0], "log-format-sd")) {
2789 if (!*(args[1])) {
2790 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
2793 }
2794 if (*(args[2])) {
2795 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
2799
2800 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2801 free(curproxy->conf.logformat_sd_string);
2802 curproxy->conf.logformat_sd_string = strdup(args[1]);
2803
2804 free(curproxy->conf.lfsd_file);
2805 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
2806 curproxy->conf.lfsd_line = curproxy->conf.args.line;
2807
2808 /* get a chance to improve log-format-sd error reporting by
2809 * reporting the correct line-number when possible.
2810 */
2811 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2812 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
2813 file, linenum, curproxy->id);
2814 err_code |= ERR_WARN;
2815 }
2816 }
2817 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
2818 if (*(args[1]) == 0) {
2819 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823 chunk_destroy(&curproxy->log_tag);
2824 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
2825 }
2826 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
2827 if (!parse_logsrv(args, &curproxy->logsrvs, (kwm == KWM_NO), &errmsg)) {
2828 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832 }
2833 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
2834 int cur_arg;
2835 int port1, port2;
2836 struct sockaddr_storage *sk;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002837
2838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2839 err_code |= ERR_WARN;
2840
2841 if (!*args[1]) {
2842 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2843 file, linenum, "source", "usesrc", "interface");
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847
Christopher Faulet31930372019-07-15 10:16:58 +02002848 /* we must first clear any optional default setting */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002849 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2850 free(curproxy->conn_src.iface_name);
2851 curproxy->conn_src.iface_name = NULL;
2852 curproxy->conn_src.iface_len = 0;
2853
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002854 sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL,
2855 &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002856 if (!sk) {
2857 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2858 file, linenum, args[0], args[1], errmsg);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002863 curproxy->conn_src.source_addr = *sk;
2864 curproxy->conn_src.opts |= CO_SRC_BIND;
2865
2866 cur_arg = 2;
2867 while (*(args[cur_arg])) {
2868 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
2869#if defined(CONFIG_HAP_TRANSPARENT)
2870 if (!*args[cur_arg + 1]) {
2871 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2872 file, linenum, "usesrc");
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (!strcmp(args[cur_arg + 1], "client")) {
2878 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2879 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
2880 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2881 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2882 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
2883 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
2884 char *name, *end;
2885
2886 name = args[cur_arg+1] + 7;
Willy Tarreau90807112020-02-25 08:16:33 +01002887 while (isspace((unsigned char)*name))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002888 name++;
2889
2890 end = name;
Willy Tarreau90807112020-02-25 08:16:33 +01002891 while (*end && !isspace((unsigned char)*end) && *end != ',' && *end != ')')
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002892 end++;
2893
2894 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2895 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
2896 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
2897 curproxy->conn_src.bind_hdr_len = end - name;
2898 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
2899 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
2900 curproxy->conn_src.bind_hdr_occ = -1;
2901
2902 /* now look for an occurrence number */
Willy Tarreau90807112020-02-25 08:16:33 +01002903 while (isspace((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002904 end++;
2905 if (*end == ',') {
2906 end++;
2907 name = end;
2908 if (*end == '-')
2909 end++;
Willy Tarreau90807112020-02-25 08:16:33 +01002910 while (isdigit((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002911 end++;
2912 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
2913 }
2914
2915 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
2916 ha_alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
2917 " occurrences values smaller than %d.\n",
2918 file, linenum, MAX_HDR_HISTORY);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922 } else {
2923 struct sockaddr_storage *sk;
2924
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002925 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, NULL,
2926 &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002927 if (!sk) {
2928 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2929 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002934 curproxy->conn_src.tproxy_addr = *sk;
2935 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
2936 }
2937 global.last_checks |= LSTCHK_NETADM;
2938#else /* no TPROXY support */
2939 ha_alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
2940 file, linenum, "usesrc");
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943#endif
2944 cur_arg += 2;
2945 continue;
2946 }
2947
2948 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2949#ifdef SO_BINDTODEVICE
2950 if (!*args[cur_arg + 1]) {
2951 ha_alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2952 file, linenum, args[0]);
2953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
2955 }
2956 free(curproxy->conn_src.iface_name);
2957 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
2958 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
2959 global.last_checks |= LSTCHK_NETADM;
2960#else
2961 ha_alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2962 file, linenum, args[0], args[cur_arg]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965#endif
2966 cur_arg += 2;
2967 continue;
2968 }
2969 ha_alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2970 file, linenum, args[0], "interface", "usesrc");
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974 }
2975 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2976 ha_alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2977 file, linenum, "usesrc", "source");
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002982 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Willy Tarreau262c3f12019-12-17 06:52:51 +01002983 "Use 'http-request replace-path', 'http-request replace-uri' or 'http-request replace-header' instead.\n",
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002984 file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002987 }
2988 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002989 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2990 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002993 }
2994 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002995 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1. "
2996 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002999 }
3000 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003001 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003004 }
3005 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003006 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3007 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003010 }
3011 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003012 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3013 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003016 }
3017 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003018 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3019 "Use 'http-request replace-header' instead.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003022 }
3023 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003024 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3025 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003028 }
3029 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003030 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3031 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003034 }
3035 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003036 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003039 }
3040 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003041 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3042 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003045 }
3046 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003047 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3048 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003051 }
3052 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003053 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3054 "Use 'http-request add-header' instead.\n", file, linenum, args[0]);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003057 }
3058 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003059 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3060 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003063 }
3064 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003065 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3066 "Use 'http-response del-header' .\n", file, linenum, args[0]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003069 }
3070 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003071 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3072 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003075 }
3076 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Balvinder Singh Rawatdef595e2020-03-14 12:11:50 +05303077 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003078 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003081 }
3082 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003083 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3084 "Use 'http-response del-header' instead.\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], "rspideny")) { /* block response header from a 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-response deny' 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], "rspadd")) { /* add response header */
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-response add-header' instead.\n", file, linenum, args[0]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003099 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003100 else {
3101 struct cfg_kw_list *kwl;
3102 int index;
3103
3104 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3105 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3106 if (kwl->kw[index].section != CFG_LISTEN)
3107 continue;
3108 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3109 /* prepare error message just in case */
3110 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
3111 if (rc < 0) {
3112 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116 else if (rc > 0) {
3117 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3118 err_code |= ERR_WARN;
3119 goto out;
3120 }
3121 goto out;
3122 }
3123 }
3124 }
3125
3126 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130 out:
3131 free(errmsg);
3132 return err_code;
3133}