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