blob: ffc575c39a4a0c6ef0f68573cc43894de8986844 [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
17#include <types/capture.h>
18#include <types/compression.h>
Willy Tarreau708c4162019-10-09 10:19:16 +020019#include <types/stats.h>
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010020
21#include <proto/acl.h>
22#include <proto/checks.h>
23#include <proto/connection.h>
Christopher Fauletf7346382019-07-17 22:02:08 +020024#include <proto/http_htx.h>
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010025#include <proto/http_rules.h>
26#include <proto/listener.h>
27#include <proto/protocol.h>
28#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;
169 char *error;
170 int rc;
171 unsigned val;
172 int err_code = 0;
173 struct acl_cond *cond = NULL;
174 struct logsrv *tmplogsrv;
175 char *errmsg = NULL;
176 struct bind_conf *bind_conf;
177
178 if (!strcmp(args[0], "listen"))
179 rc = PR_CAP_LISTEN;
180 else if (!strcmp(args[0], "frontend"))
181 rc = PR_CAP_FE;
182 else if (!strcmp(args[0], "backend"))
183 rc = PR_CAP_BE;
184 else
185 rc = PR_CAP_NONE;
186
187 if (rc != PR_CAP_NONE) { /* new proxy */
188 if (!*args[1]) {
189 ha_alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
190 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
191 file, linenum, args[0]);
192 err_code |= ERR_ALERT | ERR_ABORT;
193 goto out;
194 }
195
196 err = invalid_char(args[1]);
197 if (err) {
198 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
199 file, linenum, *err, args[0], args[1]);
200 err_code |= ERR_ALERT | ERR_FATAL;
201 }
202
203 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
204 if (curproxy) {
205 ha_alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
206 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
207 curproxy->id, curproxy->conf.file, curproxy->conf.line);
208 err_code |= ERR_ALERT | ERR_FATAL;
209 }
210
211 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
212 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
213 err_code |= ERR_ALERT | ERR_ABORT;
214 goto out;
215 }
216
217 init_new_proxy(curproxy);
218 curproxy->next = proxies_list;
219 proxies_list = curproxy;
220 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
221 curproxy->conf.args.line = curproxy->conf.line = linenum;
222 curproxy->last_change = now.tv_sec;
223 curproxy->id = strdup(args[1]);
224 curproxy->cap = rc;
225 proxy_store_name(curproxy);
226
227 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
228 if (curproxy->cap & PR_CAP_FE)
229 ha_alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
230 goto out;
231 }
232
233 /* set default values */
234 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
235 curproxy->defsrv.id = "default-server";
236
237 curproxy->state = defproxy.state;
238 curproxy->options = defproxy.options;
239 curproxy->options2 = defproxy.options2;
240 curproxy->no_options = defproxy.no_options;
241 curproxy->no_options2 = defproxy.no_options2;
242 curproxy->bind_proc = defproxy.bind_proc;
243 curproxy->except_net = defproxy.except_net;
244 curproxy->except_mask = defproxy.except_mask;
245 curproxy->except_to = defproxy.except_to;
246 curproxy->except_mask_to = defproxy.except_mask_to;
Olivier Houcharda254a372019-04-05 15:30:12 +0200247 curproxy->retry_type = defproxy.retry_type;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100248
249 if (defproxy.fwdfor_hdr_len) {
250 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
251 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
252 }
253
254 if (defproxy.orgto_hdr_len) {
255 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
256 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
257 }
258
259 if (defproxy.server_id_hdr_len) {
260 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
261 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
262 }
263
264 /* initialize error relocations */
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100265 if (!proxy_dup_default_conf_errors(curproxy, &defproxy, &errmsg)) {
266 ha_alert("parsing [%s:%d] : proxy '%s' : %s\n", file, linenum, curproxy->id, errmsg);
267 err_code |= ERR_ALERT | ERR_FATAL;
268 goto out;
269 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100270
271 if (curproxy->cap & PR_CAP_FE) {
272 curproxy->maxconn = defproxy.maxconn;
273 curproxy->backlog = defproxy.backlog;
274 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
275
276 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +0100277 curproxy->max_out_conns = defproxy.max_out_conns;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100278 }
279
280 if (curproxy->cap & PR_CAP_BE) {
281 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau76e84f52019-01-14 16:50:58 +0100282 curproxy->lbprm.hash_balance_factor = defproxy.lbprm.hash_balance_factor;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100283 curproxy->fullconn = defproxy.fullconn;
284 curproxy->conn_retries = defproxy.conn_retries;
285 curproxy->redispatch_after = defproxy.redispatch_after;
286 curproxy->max_ka_queue = defproxy.max_ka_queue;
287
288 if (defproxy.check_req) {
289 curproxy->check_req = calloc(1, defproxy.check_len);
290 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
291 }
292 curproxy->check_len = defproxy.check_len;
293
294 if (defproxy.expect_str) {
295 curproxy->expect_str = strdup(defproxy.expect_str);
296 if (defproxy.expect_regex) {
297 /* note: this regex is known to be valid */
Dragan Dosen26743032019-04-30 15:54:36 +0200298 error = NULL;
299 if (!(curproxy->expect_regex = regex_comp(defproxy.expect_str, 1, 1, &error))) {
300 ha_alert("parsing [%s:%d] : regular expression '%s' : %s\n", file, linenum,
301 defproxy.expect_str, error);
302 free(error);
303 err_code |= ERR_ALERT | ERR_FATAL;
304 goto out;
305 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100306 }
307 }
308
309 curproxy->ck_opts = defproxy.ck_opts;
310 if (defproxy.cookie_name)
311 curproxy->cookie_name = strdup(defproxy.cookie_name);
312 curproxy->cookie_len = defproxy.cookie_len;
313
314 if (defproxy.dyncookie_key)
315 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
316 if (defproxy.cookie_domain)
317 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
318
319 if (defproxy.cookie_maxidle)
320 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
321
322 if (defproxy.cookie_maxlife)
323 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
324
325 if (defproxy.rdp_cookie_name)
326 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
327 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
328
Christopher Faulet2f533902020-01-21 11:06:48 +0100329 if (defproxy.cookie_attrs)
330 curproxy->cookie_attrs = strdup(defproxy.cookie_attrs);
Willy Tarreau20e68372019-01-14 16:04:01 +0100331
Willy Tarreau4c03d1c2019-01-14 15:23:54 +0100332 if (defproxy.lbprm.arg_str)
333 curproxy->lbprm.arg_str = strdup(defproxy.lbprm.arg_str);
334 curproxy->lbprm.arg_len = defproxy.lbprm.arg_len;
Willy Tarreau20e68372019-01-14 16:04:01 +0100335 curproxy->lbprm.arg_opt1 = defproxy.lbprm.arg_opt1;
336 curproxy->lbprm.arg_opt2 = defproxy.lbprm.arg_opt2;
337 curproxy->lbprm.arg_opt3 = defproxy.lbprm.arg_opt3;
338
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100339 if (defproxy.conn_src.iface_name)
340 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
341 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
342 curproxy->conn_src.opts = defproxy.conn_src.opts;
343#if defined(CONFIG_HAP_TRANSPARENT)
344 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
345#endif
346 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
347 }
348
349 if (curproxy->cap & PR_CAP_FE) {
350 if (defproxy.capture_name)
351 curproxy->capture_name = strdup(defproxy.capture_name);
352 curproxy->capture_namelen = defproxy.capture_namelen;
353 curproxy->capture_len = defproxy.capture_len;
354 }
355
356 if (curproxy->cap & PR_CAP_FE) {
357 curproxy->timeout.client = defproxy.timeout.client;
358 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
359 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
360 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
361 curproxy->timeout.httpka = defproxy.timeout.httpka;
362 curproxy->mon_net = defproxy.mon_net;
363 curproxy->mon_mask = defproxy.mon_mask;
364 if (defproxy.monitor_uri)
365 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
366 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
367 if (defproxy.defbe.name)
368 curproxy->defbe.name = strdup(defproxy.defbe.name);
369
370 /* get either a pointer to the logformat string or a copy of it */
371 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
372 if (curproxy->conf.logformat_string &&
373 curproxy->conf.logformat_string != default_http_log_format &&
374 curproxy->conf.logformat_string != default_tcp_log_format &&
375 curproxy->conf.logformat_string != clf_http_log_format)
376 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
377
378 if (defproxy.conf.lfs_file) {
379 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
380 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
381 }
382
383 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
384 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
385 if (curproxy->conf.logformat_sd_string &&
386 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
387 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
388
389 if (defproxy.conf.lfsd_file) {
390 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
391 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
392 }
393 }
394
395 if (curproxy->cap & PR_CAP_BE) {
396 curproxy->timeout.connect = defproxy.timeout.connect;
397 curproxy->timeout.server = defproxy.timeout.server;
398 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
399 curproxy->timeout.check = defproxy.timeout.check;
400 curproxy->timeout.queue = defproxy.timeout.queue;
401 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
402 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
403 curproxy->timeout.httpka = defproxy.timeout.httpka;
404 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
405 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
406 }
407
408 curproxy->mode = defproxy.mode;
409 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
410
411 /* copy default logsrvs to curproxy */
412 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
413 struct logsrv *node = malloc(sizeof(*node));
414 memcpy(node, tmplogsrv, sizeof(struct logsrv));
415 node->ref = tmplogsrv->ref;
416 LIST_INIT(&node->list);
417 LIST_ADDQ(&curproxy->logsrvs, &node->list);
418 }
419
420 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
421 if (curproxy->conf.uniqueid_format_string)
422 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
423
424 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
425
426 if (defproxy.conf.uif_file) {
427 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
428 curproxy->conf.uif_line = defproxy.conf.uif_line;
429 }
430
431 /* copy default header unique id */
Tim Duesterhus0643b0e2020-03-05 17:56:35 +0100432 if (isttest(defproxy.header_unique_id)) {
433 const struct ist copy = istdup(defproxy.header_unique_id);
434 if (!isttest(copy)) {
435 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
436 err_code |= ERR_ALERT | ERR_FATAL;
437 goto out;
438 }
439 curproxy->header_unique_id = copy;
440 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100441
442 /* default compression options */
443 if (defproxy.comp != NULL) {
444 curproxy->comp = calloc(1, sizeof(struct comp));
445 curproxy->comp->algos = defproxy.comp->algos;
446 curproxy->comp->types = defproxy.comp->types;
447 }
448
449 curproxy->grace = defproxy.grace;
450 curproxy->conf.used_listener_id = EB_ROOT;
451 curproxy->conf.used_server_id = EB_ROOT;
452
453 if (defproxy.check_path)
454 curproxy->check_path = strdup(defproxy.check_path);
455 if (defproxy.check_command)
456 curproxy->check_command = strdup(defproxy.check_command);
457
458 if (defproxy.email_alert.mailers.name)
459 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
460 if (defproxy.email_alert.from)
461 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
462 if (defproxy.email_alert.to)
463 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
464 if (defproxy.email_alert.myhostname)
465 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
466 curproxy->email_alert.level = defproxy.email_alert.level;
467 curproxy->email_alert.set = defproxy.email_alert.set;
468
469 goto out;
470 }
471 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
472 /* some variables may have already been initialized earlier */
473 /* FIXME-20070101: we should do this too at the end of the
474 * config parsing to free all default values.
475 */
476 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
477 err_code |= ERR_ABORT;
478 goto out;
479 }
480
481 free(defproxy.check_req);
482 free(defproxy.check_command);
483 free(defproxy.check_path);
484 free(defproxy.cookie_name);
485 free(defproxy.rdp_cookie_name);
486 free(defproxy.dyncookie_key);
487 free(defproxy.cookie_domain);
Christopher Faulet2f533902020-01-21 11:06:48 +0100488 free(defproxy.cookie_attrs);
Willy Tarreau4c03d1c2019-01-14 15:23:54 +0100489 free(defproxy.lbprm.arg_str);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100490 free(defproxy.capture_name);
491 free(defproxy.monitor_uri);
492 free(defproxy.defbe.name);
493 free(defproxy.conn_src.iface_name);
494 free(defproxy.fwdfor_hdr_name);
495 defproxy.fwdfor_hdr_len = 0;
496 free(defproxy.orgto_hdr_name);
497 defproxy.orgto_hdr_len = 0;
498 free(defproxy.server_id_hdr_name);
499 defproxy.server_id_hdr_len = 0;
500 free(defproxy.expect_str);
Dragan Dosen26743032019-04-30 15:54:36 +0200501 regex_free(defproxy.expect_regex);
502 defproxy.expect_regex = NULL;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100503
504 if (defproxy.conf.logformat_string != default_http_log_format &&
505 defproxy.conf.logformat_string != default_tcp_log_format &&
506 defproxy.conf.logformat_string != clf_http_log_format)
507 free(defproxy.conf.logformat_string);
508
509 free(defproxy.conf.uniqueid_format_string);
510 free(defproxy.conf.lfs_file);
511 free(defproxy.conf.uif_file);
512 chunk_destroy(&defproxy.log_tag);
513 free_email_alert(&defproxy);
514
515 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
516 free(defproxy.conf.logformat_sd_string);
517 free(defproxy.conf.lfsd_file);
518
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100519 proxy_release_conf_errors(&defproxy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100520
521 /* we cannot free uri_auth because it might already be used */
522 init_default_instance();
523 curproxy = &defproxy;
524 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
525 curproxy->conf.args.line = curproxy->conf.line = linenum;
526 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
527 goto out;
528 }
529 else if (curproxy == NULL) {
530 ha_alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534
535 /* update the current file and line being parsed */
536 curproxy->conf.args.file = curproxy->conf.file;
537 curproxy->conf.args.line = linenum;
538
539 /* Now let's parse the proxy-specific keywords */
540 if (!strcmp(args[0], "server") ||
541 !strcmp(args[0], "default-server") ||
542 !strcmp(args[0], "server-template")) {
Frédéric Lécaille355b2032019-01-11 14:06:12 +0100543 err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100544 if (err_code & ERR_FATAL)
545 goto out;
546 }
547 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
548 struct listener *l;
549 int cur_arg;
550
551 if (curproxy == &defproxy) {
552 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
557 err_code |= ERR_WARN;
558
559 if (!*(args[1])) {
560 ha_alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
561 file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565
566 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
567
568 /* use default settings for unix sockets */
569 bind_conf->ux.uid = global.unix_bind.ux.uid;
570 bind_conf->ux.gid = global.unix_bind.ux.gid;
571 bind_conf->ux.mode = global.unix_bind.ux.mode;
572
573 /* NOTE: the following line might create several listeners if there
574 * are comma-separated IPs or port ranges. So all further processing
575 * will have to be applied to all listeners created after last_listen.
576 */
577 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
578 if (errmsg && *errmsg) {
579 indent_msg(&errmsg, 2);
580 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
581 }
582 else
583 ha_alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
584 file, linenum, args[0], args[1]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588
589 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
590 /* Set default global rights and owner for unix bind */
591 global.maxsock++;
592 }
593
594 cur_arg = 2;
595 while (*(args[cur_arg])) {
596 static int bind_dumped;
597 struct bind_kw *kw;
598 char *err;
599
600 kw = bind_find_kw(args[cur_arg]);
601 if (kw) {
602 char *err = NULL;
603 int code;
604
605 if (!kw->parse) {
606 ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
607 file, linenum, args[0], args[1], args[cur_arg]);
608 cur_arg += 1 + kw->skip ;
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612
613 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
614 err_code |= code;
615
616 if (code) {
617 if (err && *err) {
618 indent_msg(&err, 2);
Emeric Brun0655c9b2019-10-17 16:45:56 +0200619 if (((code & (ERR_WARN|ERR_ALERT)) == ERR_WARN))
620 ha_warning("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
621 else
622 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100623 }
624 else
625 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
626 file, linenum, args[0], args[1], args[cur_arg]);
627 if (code & ERR_FATAL) {
628 free(err);
629 cur_arg += 1 + kw->skip;
630 goto out;
631 }
632 }
633 free(err);
634 cur_arg += 1 + kw->skip;
635 continue;
636 }
637
638 err = NULL;
639 if (!bind_dumped) {
640 bind_dump_kws(&err);
641 indent_msg(&err, 4);
642 bind_dumped = 1;
643 }
644
645 ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
646 file, linenum, args[0], args[1], args[cur_arg],
647 err ? " Registered keywords :" : "", err ? err : "");
648 free(err);
649
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 goto out;
654 }
655 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
656 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
657 ha_alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
658 file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
663 err_code |= ERR_WARN;
664
665 /* flush useless bits */
666 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
667 goto out;
668 }
669 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
670 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
671 err_code |= ERR_WARN;
672
673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
675
676 if (!*args[1]) {
677 ha_alert("parsing [%s:%d] : '%s' expects an URI.\n",
678 file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682
683 free(curproxy->monitor_uri);
684 curproxy->monitor_uri_len = strlen(args[1]);
685 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
686 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
687 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
688
689 goto out;
690 }
691 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
692 if (alertif_too_many_args(1, file, linenum, args, &err_code))
693 goto out;
694
695 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
696 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
697 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
698 else {
699 ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703 }
704 else if (!strcmp(args[0], "id")) {
705 struct eb32_node *node;
706
707 if (curproxy == &defproxy) {
708 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713
714 if (alertif_too_many_args(1, file, linenum, args, &err_code))
715 goto out;
716
717 if (!*args[1]) {
718 ha_alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723
724 curproxy->uuid = atol(args[1]);
725 curproxy->conf.id.key = curproxy->uuid;
726 curproxy->options |= PR_O_FORCED_ID;
727
728 if (curproxy->uuid <= 0) {
729 ha_alert("parsing [%s:%d]: custom id has to be > 0.\n",
730 file, linenum);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
736 if (node) {
737 struct proxy *target = container_of(node, struct proxy, conf.id);
738 ha_alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
739 file, linenum, proxy_type_str(curproxy), curproxy->id,
740 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 eb32_insert(&used_proxy_id, &curproxy->conf.id);
745 }
746 else if (!strcmp(args[0], "description")) {
747 int i, len=0;
748 char *d;
749
750 if (curproxy == &defproxy) {
751 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 if (!*args[1]) {
758 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
759 file, linenum, args[0]);
760 return -1;
761 }
762
763 for (i = 1; *args[i]; i++)
764 len += strlen(args[i]) + 1;
765
766 d = calloc(1, len);
767 curproxy->desc = d;
768
769 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
770 for (i = 2; *args[i]; i++)
771 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
772
773 }
774 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
775 if (alertif_too_many_args(0, file, linenum, args, &err_code))
776 goto out;
777 curproxy->state = PR_STSTOPPED;
778 }
779 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
780 if (alertif_too_many_args(0, file, linenum, args, &err_code))
781 goto out;
782 curproxy->state = PR_STNEW;
783 }
784 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
785 int cur_arg = 1;
786 unsigned long set = 0;
787
788 while (*args[cur_arg]) {
789 if (strcmp(args[cur_arg], "all") == 0) {
790 set = 0;
791 break;
792 }
Willy Tarreauff9c9142019-02-07 10:39:36 +0100793 if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, &errmsg)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100794 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 cur_arg++;
799 }
800 curproxy->bind_proc = set;
801 }
802 else if (!strcmp(args[0], "acl")) { /* add an ACL */
803 if (curproxy == &defproxy) {
804 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808
809 err = invalid_char(args[1]);
810 if (err) {
811 ha_alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
812 file, linenum, *err, args[1]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100817 if (strcasecmp(args[1], "or") == 0) {
Tim Duesterhusf1bc24c2020-02-06 22:04:03 +0100818 ha_alert("parsing [%s:%d] : acl name '%s' will never match. 'or' is used to express a "
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100819 "logical disjunction within a condition.\n",
820 file, linenum, args[1]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100825 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
826 ha_alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
827 file, linenum, args[1], errmsg);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 }
832 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
833
834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
835 err_code |= ERR_WARN;
836
837 if (*(args[1]) == 0) {
838 ha_alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
839 file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 free(curproxy->dyncookie_key);
844 curproxy->dyncookie_key = strdup(args[1]);
845 }
846 else if (!strcmp(args[0], "cookie")) { /* cookie name */
847 int cur_arg;
848
849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
850 err_code |= ERR_WARN;
851
852 if (*(args[1]) == 0) {
853 ha_alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
854 file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858
859 curproxy->ck_opts = 0;
860 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
861 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
862 free(curproxy->cookie_name);
863 curproxy->cookie_name = strdup(args[1]);
864 curproxy->cookie_len = strlen(curproxy->cookie_name);
865
866 cur_arg = 2;
867 while (*(args[cur_arg])) {
868 if (!strcmp(args[cur_arg], "rewrite")) {
869 curproxy->ck_opts |= PR_CK_RW;
870 }
871 else if (!strcmp(args[cur_arg], "indirect")) {
872 curproxy->ck_opts |= PR_CK_IND;
873 }
874 else if (!strcmp(args[cur_arg], "insert")) {
875 curproxy->ck_opts |= PR_CK_INS;
876 }
877 else if (!strcmp(args[cur_arg], "nocache")) {
878 curproxy->ck_opts |= PR_CK_NOC;
879 }
880 else if (!strcmp(args[cur_arg], "postonly")) {
881 curproxy->ck_opts |= PR_CK_POST;
882 }
883 else if (!strcmp(args[cur_arg], "preserve")) {
884 curproxy->ck_opts |= PR_CK_PSV;
885 }
886 else if (!strcmp(args[cur_arg], "prefix")) {
887 curproxy->ck_opts |= PR_CK_PFX;
888 }
889 else if (!strcmp(args[cur_arg], "httponly")) {
890 curproxy->ck_opts |= PR_CK_HTTPONLY;
891 }
892 else if (!strcmp(args[cur_arg], "secure")) {
893 curproxy->ck_opts |= PR_CK_SECURE;
894 }
895 else if (!strcmp(args[cur_arg], "domain")) {
896 if (!*args[cur_arg + 1]) {
897 ha_alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
898 file, linenum, args[cur_arg]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902
Joao Moraise1583752019-10-30 21:04:00 -0300903 if (!strchr(args[cur_arg + 1], '.')) {
904 /* rfc6265, 5.2.3 The Domain Attribute */
905 ha_warning("parsing [%s:%d]: domain '%s' contains no embedded dot,"
906 " this configuration may not work properly (see RFC6265#5.2.3).\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100907 file, linenum, args[cur_arg + 1]);
908 err_code |= ERR_WARN;
909 }
910
911 err = invalid_domainchar(args[cur_arg + 1]);
912 if (err) {
913 ha_alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
914 file, linenum, *err, args[cur_arg + 1]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918
919 if (!curproxy->cookie_domain) {
920 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
921 } else {
922 /* one domain was already specified, add another one by
923 * building the string which will be returned along with
924 * the cookie.
925 */
926 char *new_ptr;
927 int new_len = strlen(curproxy->cookie_domain) +
928 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
929 new_ptr = malloc(new_len);
930 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
931 free(curproxy->cookie_domain);
932 curproxy->cookie_domain = new_ptr;
933 }
934 cur_arg++;
935 }
936 else if (!strcmp(args[cur_arg], "maxidle")) {
937 unsigned int maxidle;
938 const char *res;
939
940 if (!*args[cur_arg + 1]) {
941 ha_alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
942 file, linenum, args[cur_arg]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946
947 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200948 if (res == PARSE_TIME_OVER) {
949 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
950 file, linenum, args[cur_arg+1], args[cur_arg]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 else if (res == PARSE_TIME_UNDER) {
955 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
956 file, linenum, args[cur_arg+1], args[cur_arg]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100961 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
962 file, linenum, *res, args[cur_arg]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 curproxy->cookie_maxidle = maxidle;
967 cur_arg++;
968 }
969 else if (!strcmp(args[cur_arg], "maxlife")) {
970 unsigned int maxlife;
971 const char *res;
972
973 if (!*args[cur_arg + 1]) {
974 ha_alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
975 file, linenum, args[cur_arg]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
Willy Tarreau9faebe32019-06-07 19:00:37 +0200980
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100981 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200982 if (res == PARSE_TIME_OVER) {
983 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
984 file, linenum, args[cur_arg+1], args[cur_arg]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 else if (res == PARSE_TIME_UNDER) {
989 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
990 file, linenum, args[cur_arg+1], args[cur_arg]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100995 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
996 file, linenum, *res, args[cur_arg]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 curproxy->cookie_maxlife = maxlife;
1001 cur_arg++;
1002 }
1003 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
1004
1005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
1006 err_code |= ERR_WARN;
1007 curproxy->ck_opts |= PR_CK_DYNAMIC;
1008 }
Christopher Faulet2f533902020-01-21 11:06:48 +01001009 else if (!strcmp(args[cur_arg], "attr")) {
1010 char *val;
1011 if (!*args[cur_arg + 1]) {
1012 ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
1013 file, linenum, args[cur_arg]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 val = args[cur_arg + 1];
1018 while (*val) {
Willy Tarreau90807112020-02-25 08:16:33 +01001019 if (iscntrl((unsigned char)*val) || *val == ';') {
Christopher Faulet2f533902020-01-21 11:06:48 +01001020 ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
1021 file, linenum, *val);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025 val++;
1026 }
1027 /* don't add ';' for the first attribute */
1028 if (!curproxy->cookie_attrs)
1029 curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
1030 else
1031 memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
1032 cur_arg++;
1033 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001034
1035 else {
Christopher Faulet2f533902020-01-21 11:06:48 +01001036 ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic', 'maxlife' and 'attr' options.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001037 file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 cur_arg++;
1042 }
1043 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
1044 ha_alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1045 file, linenum);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 }
1048
1049 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
1050 ha_alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1051 file, linenum);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 }
1054
1055 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
1056 ha_alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
1057 file, linenum);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 }
1060 }/* end else if (!strcmp(args[0], "cookie")) */
1061 else if (!strcmp(args[0], "email-alert")) {
1062 if (*(args[1]) == 0) {
1063 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1064 file, linenum, args[0]);
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067 }
1068
1069 if (!strcmp(args[1], "from")) {
1070 if (*(args[1]) == 0) {
1071 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1072 file, linenum, args[1]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 free(curproxy->email_alert.from);
1077 curproxy->email_alert.from = strdup(args[2]);
1078 }
1079 else if (!strcmp(args[1], "mailers")) {
1080 if (*(args[1]) == 0) {
1081 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1082 file, linenum, args[1]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 free(curproxy->email_alert.mailers.name);
1087 curproxy->email_alert.mailers.name = strdup(args[2]);
1088 }
1089 else if (!strcmp(args[1], "myhostname")) {
1090 if (*(args[1]) == 0) {
1091 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1092 file, linenum, args[1]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 free(curproxy->email_alert.myhostname);
1097 curproxy->email_alert.myhostname = strdup(args[2]);
1098 }
1099 else if (!strcmp(args[1], "level")) {
1100 curproxy->email_alert.level = get_log_level(args[2]);
1101 if (curproxy->email_alert.level < 0) {
1102 ha_alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
1103 file, linenum, args[1], args[2]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107 }
1108 else if (!strcmp(args[1], "to")) {
1109 if (*(args[1]) == 0) {
1110 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1111 file, linenum, args[1]);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
1114 }
1115 free(curproxy->email_alert.to);
1116 curproxy->email_alert.to = strdup(args[2]);
1117 }
1118 else {
1119 ha_alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
1120 file, linenum, args[1]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123 }
1124 /* Indicate that the email_alert is at least partially configured */
1125 curproxy->email_alert.set = 1;
1126 }/* end else if (!strcmp(args[0], "email-alert")) */
1127 else if (!strcmp(args[0], "external-check")) {
1128 if (*(args[1]) == 0) {
1129 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1130 file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
1134
1135 if (!strcmp(args[1], "command")) {
1136 if (alertif_too_many_args(2, file, linenum, args, &err_code))
1137 goto out;
1138 if (*(args[2]) == 0) {
1139 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1140 file, linenum, args[1]);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
1143 }
1144 free(curproxy->check_command);
1145 curproxy->check_command = strdup(args[2]);
1146 }
1147 else if (!strcmp(args[1], "path")) {
1148 if (alertif_too_many_args(2, file, linenum, args, &err_code))
1149 goto out;
1150 if (*(args[2]) == 0) {
1151 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1152 file, linenum, args[1]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156 free(curproxy->check_path);
1157 curproxy->check_path = strdup(args[2]);
1158 }
1159 else {
1160 ha_alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
1161 file, linenum, args[1]);
1162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
1165 }/* end else if (!strcmp(args[0], "external-check")) */
1166 else if (!strcmp(args[0], "persist")) { /* persist */
1167 if (*(args[1]) == 0) {
1168 ha_alert("parsing [%s:%d] : missing persist method.\n",
1169 file, linenum);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172 }
1173
1174 if (!strncmp(args[1], "rdp-cookie", 10)) {
1175 curproxy->options2 |= PR_O2_RDPC_PRST;
1176
1177 if (*(args[1] + 10) == '(') { /* cookie name */
1178 const char *beg, *end;
1179
1180 beg = args[1] + 11;
1181 end = strchr(beg, ')');
1182
1183 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1184 goto out;
1185
1186 if (!end || end == beg) {
1187 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1188 file, linenum);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191 }
1192
1193 free(curproxy->rdp_cookie_name);
1194 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1195 curproxy->rdp_cookie_len = end-beg;
1196 }
1197 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
1198 free(curproxy->rdp_cookie_name);
1199 curproxy->rdp_cookie_name = strdup("msts");
1200 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1201 }
1202 else { /* syntax */
1203 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1204 file, linenum);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 }
1209 else {
1210 ha_alert("parsing [%s:%d] : unknown persist method.\n",
1211 file, linenum);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214 }
1215 }
1216 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Tim Duesterhus473c2832019-05-06 01:19:52 +02001217 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 +01001218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221 else if (!strcmp(args[0], "load-server-state-from-file")) {
1222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1223 err_code |= ERR_WARN;
1224 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
1225 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
1226 }
1227 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
1228 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
1229 }
1230 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
1231 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
1232 }
1233 else {
1234 ha_alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
1235 file, linenum, args[0], args[1]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239 }
1240 else if (!strcmp(args[0], "server-state-file-name")) {
1241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1242 err_code |= ERR_WARN;
1243 if (*(args[1]) == 0) {
1244 ha_alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
1245 file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 else if (!strcmp(args[1], "use-backend-name"))
1250 curproxy->server_state_file_name = strdup(curproxy->id);
1251 else
1252 curproxy->server_state_file_name = strdup(args[1]);
1253 }
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +01001254 else if (!strcmp(args[0], "max-session-srv-conns")) {
1255 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1256 err_code |= ERR_WARN;
1257 if (*(args[1]) == 0) {
1258 ha_alert("parsine [%s:%d] : '%s' expects a number. Got no argument\n",
1259 file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 curproxy->max_out_conns = atoi(args[1]);
1264 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001265 else if (!strcmp(args[0], "capture")) {
1266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1267 err_code |= ERR_WARN;
1268
1269 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1270 if (curproxy == &defproxy) {
1271 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275
1276 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1277 goto out;
1278
1279 if (*(args[4]) == 0) {
1280 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1281 file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 free(curproxy->capture_name);
1286 curproxy->capture_name = strdup(args[2]);
1287 curproxy->capture_namelen = strlen(curproxy->capture_name);
1288 curproxy->capture_len = atol(args[4]);
1289 curproxy->to_log |= LW_COOKIE;
1290 }
1291 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1292 struct cap_hdr *hdr;
1293
1294 if (curproxy == &defproxy) {
1295 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
1300 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1301 goto out;
1302
1303 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1304 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1305 file, linenum, args[0], args[1]);
1306 err_code |= ERR_ALERT | ERR_FATAL;
1307 goto out;
1308 }
1309
1310 hdr = calloc(1, sizeof(*hdr));
1311 hdr->next = curproxy->req_cap;
1312 hdr->name = strdup(args[3]);
1313 hdr->namelen = strlen(args[3]);
1314 hdr->len = atol(args[5]);
1315 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1316 hdr->index = curproxy->nb_req_cap++;
1317 curproxy->req_cap = hdr;
1318 curproxy->to_log |= LW_REQHDR;
1319 }
1320 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1321 struct cap_hdr *hdr;
1322
1323 if (curproxy == &defproxy) {
1324 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
1328
1329 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1330 goto out;
1331
1332 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1333 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1334 file, linenum, args[0], args[1]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 hdr = calloc(1, sizeof(*hdr));
1339 hdr->next = curproxy->rsp_cap;
1340 hdr->name = strdup(args[3]);
1341 hdr->namelen = strlen(args[3]);
1342 hdr->len = atol(args[5]);
1343 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1344 hdr->index = curproxy->nb_rsp_cap++;
1345 curproxy->rsp_cap = hdr;
1346 curproxy->to_log |= LW_RSPHDR;
1347 }
1348 else {
1349 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1350 file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354 }
1355 else if (!strcmp(args[0], "retries")) { /* connection retries */
1356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1357 err_code |= ERR_WARN;
1358
1359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
1361
1362 if (*(args[1]) == 0) {
1363 ha_alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1364 file, linenum, args[0]);
1365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
1367 }
1368 curproxy->conn_retries = atol(args[1]);
1369 }
1370 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1371 struct act_rule *rule;
1372
1373 if (curproxy == &defproxy) {
1374 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377 }
1378
1379 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
1380 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001381 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001382 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1383 file, linenum, args[0]);
1384 err_code |= ERR_WARN;
1385 }
1386
1387 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
1388
1389 if (!rule) {
1390 err_code |= ERR_ALERT | ERR_ABORT;
1391 goto out;
1392 }
1393
1394 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
1395 err_code |= warnif_cond_conflicts(rule->cond,
1396 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1397 file, linenum);
1398
1399 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
1400 }
1401 else if (!strcmp(args[0], "http-response")) { /* response access control */
1402 struct act_rule *rule;
1403
1404 if (curproxy == &defproxy) {
1405 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto out;
1408 }
1409
1410 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
1411 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001412 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001413 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1414 file, linenum, args[0]);
1415 err_code |= ERR_WARN;
1416 }
1417
1418 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
1419
1420 if (!rule) {
1421 err_code |= ERR_ALERT | ERR_ABORT;
1422 goto out;
1423 }
1424
1425 err_code |= warnif_cond_conflicts(rule->cond,
1426 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1427 file, linenum);
1428
1429 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
1430 }
Christopher Faulet6d0c3df2020-01-22 09:26:35 +01001431 else if (!strcmp(args[0], "http-after-response")) {
1432 struct act_rule *rule;
1433
1434 if (curproxy == &defproxy) {
1435 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
1440 if (!LIST_ISEMPTY(&curproxy->http_after_res_rules) &&
1441 !LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->cond &&
1442 (LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
1443 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1444 file, linenum, args[0]);
1445 err_code |= ERR_WARN;
1446 }
1447
1448 rule = parse_http_after_res_cond((const char **)args + 1, file, linenum, curproxy);
1449
1450 if (!rule) {
1451 err_code |= ERR_ALERT | ERR_ABORT;
1452 goto out;
1453 }
1454
1455 err_code |= warnif_cond_conflicts(rule->cond,
1456 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1457 file, linenum);
1458
1459 LIST_ADDQ(&curproxy->http_after_res_rules, &rule->list);
1460 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001461 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
1462 /* set the header name and length into the proxy structure */
1463 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1464 err_code |= ERR_WARN;
1465
1466 if (!*args[1]) {
1467 ha_alert("parsing [%s:%d] : '%s' requires a header string.\n",
1468 file, linenum, args[0]);
1469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
1471 }
1472
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001473 /* set the desired header name, in lower case */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001474 free(curproxy->server_id_hdr_name);
1475 curproxy->server_id_hdr_name = strdup(args[1]);
1476 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001477 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 +01001478 }
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001479 else if (!strcmp(args[0], "block")) {
1480 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 +01001481
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001484 }
1485 else if (!strcmp(args[0], "redirect")) {
1486 struct redirect_rule *rule;
1487
1488 if (curproxy == &defproxy) {
1489 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
1495 ha_alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
1496 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
1497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
1499 }
1500
1501 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1502 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
1503 err_code |= warnif_cond_conflicts(rule->cond,
1504 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1505 file, linenum);
1506 }
1507 else if (!strcmp(args[0], "use_backend")) {
1508 struct switching_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_FE, 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 backend 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 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1527 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1528 file, linenum, errmsg);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532
1533 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
1534 }
1535 else if (*args[2]) {
1536 ha_alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
1537 file, linenum, args[2]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541
1542 rule = calloc(1, sizeof(*rule));
1543 if (!rule) {
1544 ha_alert("Out of memory error.\n");
1545 goto out;
1546 }
1547 rule->cond = cond;
1548 rule->be.name = strdup(args[1]);
1549 rule->line = linenum;
1550 rule->file = strdup(file);
1551 if (!rule->file) {
1552 ha_alert("Out of memory error.\n");
1553 goto out;
1554 }
1555 LIST_INIT(&rule->list);
1556 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1557 }
1558 else if (strcmp(args[0], "use-server") == 0) {
1559 struct server_rule *rule;
1560
1561 if (curproxy == &defproxy) {
1562 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
1565 }
1566
1567 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1568 err_code |= ERR_WARN;
1569
1570 if (*(args[1]) == 0) {
1571 ha_alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
1572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
1574 }
1575
1576 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1577 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1578 file, linenum, args[0]);
1579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
1581 }
1582
1583 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1584 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1585 file, linenum, errmsg);
1586 err_code |= ERR_ALERT | ERR_FATAL;
1587 goto out;
1588 }
1589
1590 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1591
1592 rule = calloc(1, sizeof(*rule));
1593 rule->cond = cond;
1594 rule->srv.name = strdup(args[1]);
Jerome Magnin824186b2020-03-29 09:37:12 +02001595 rule->line = linenum;
1596 rule->file = strdup(file);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001597 LIST_INIT(&rule->list);
1598 LIST_ADDQ(&curproxy->server_rules, &rule->list);
1599 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
1600 }
1601 else if ((!strcmp(args[0], "force-persist")) ||
1602 (!strcmp(args[0], "ignore-persist"))) {
1603 struct persist_rule *rule;
1604
1605 if (curproxy == &defproxy) {
1606 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
1609 }
1610
1611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1612 err_code |= ERR_WARN;
1613
1614 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
1615 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1616 file, linenum, args[0]);
1617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
1619 }
1620
1621 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
1622 ha_alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
1623 file, linenum, args[0], errmsg);
1624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
1626 }
1627
1628 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
1629 * where force-persist is applied.
1630 */
1631 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
1632
1633 rule = calloc(1, sizeof(*rule));
1634 rule->cond = cond;
1635 if (!strcmp(args[0], "force-persist")) {
1636 rule->type = PERSIST_TYPE_FORCE;
1637 } else {
1638 rule->type = PERSIST_TYPE_IGNORE;
1639 }
1640 LIST_INIT(&rule->list);
1641 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
1642 }
1643 else if (!strcmp(args[0], "stick-table")) {
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001644 struct stktable *other;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001645
1646 if (curproxy == &defproxy) {
1647 ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
1648 file, linenum);
1649 err_code |= ERR_ALERT | ERR_FATAL;
1650 goto out;
1651 }
1652
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001653 other = stktable_find_by_name(curproxy->id);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001654 if (other) {
1655 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 +01001656 file, linenum, curproxy->id,
1657 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
1658 other->proxy ? other->id : other->peers.p->id,
1659 other->conf.file, other->conf.line);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001664 curproxy->table = calloc(1, sizeof *curproxy->table);
1665 if (!curproxy->table) {
1666 ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
1667 file, linenum, args[0], args[1]);
1668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
1671
Frédéric Lécaillec02766a2019-03-20 15:06:55 +01001672 err_code |= parse_stick_table(file, linenum, args, curproxy->table,
1673 curproxy->id, curproxy->id, NULL);
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001674 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001675 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001676
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001677 /* Store the proxy in the stick-table. */
1678 curproxy->table->proxy = curproxy;
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001679
1680 stktable_store_name(curproxy->table);
1681 curproxy->table->next = stktables_list;
1682 stktables_list = curproxy->table;
Frédéric Lécaille015e4d72019-03-19 14:55:01 +01001683
1684 /* Add this proxy to the list of proxies which refer to its stick-table. */
1685 if (curproxy->table->proxies_list != curproxy) {
1686 curproxy->next_stkt_ref = curproxy->table->proxies_list;
1687 curproxy->table->proxies_list = curproxy;
1688 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001689 }
1690 else if (!strcmp(args[0], "stick")) {
1691 struct sticking_rule *rule;
1692 struct sample_expr *expr;
1693 int myidx = 0;
1694 const char *name = NULL;
1695 int flags;
1696
1697 if (curproxy == &defproxy) {
1698 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
1701 }
1702
1703 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
1704 err_code |= ERR_WARN;
1705 goto out;
1706 }
1707
1708 myidx++;
1709 if ((strcmp(args[myidx], "store") == 0) ||
1710 (strcmp(args[myidx], "store-request") == 0)) {
1711 myidx++;
1712 flags = STK_IS_STORE;
1713 }
1714 else if (strcmp(args[myidx], "store-response") == 0) {
1715 myidx++;
1716 flags = STK_IS_STORE | STK_ON_RSP;
1717 }
1718 else if (strcmp(args[myidx], "match") == 0) {
1719 myidx++;
1720 flags = STK_IS_MATCH;
1721 }
1722 else if (strcmp(args[myidx], "on") == 0) {
1723 myidx++;
1724 flags = STK_IS_MATCH | STK_IS_STORE;
1725 }
1726 else {
1727 ha_alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731
1732 if (*(args[myidx]) == 0) {
1733 ha_alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
1734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
1736 }
1737
1738 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreaue3b57bf2020-02-14 16:50:14 +01001739 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001740 if (!expr) {
1741 ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
1742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
1744 }
1745
1746 if (flags & STK_ON_RSP) {
1747 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
1748 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
1749 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 free(expr);
1752 goto out;
1753 }
1754 } else {
1755 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
1756 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
1757 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1758 err_code |= ERR_ALERT | ERR_FATAL;
1759 free(expr);
1760 goto out;
1761 }
1762 }
1763
Christopher Faulet711ed6a2019-07-16 14:16:10 +02001764 /* check if we need to allocate an http_txn struct for HTTP parsing */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001765 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
1766
1767 if (strcmp(args[myidx], "table") == 0) {
1768 myidx++;
1769 name = args[myidx++];
1770 }
1771
1772 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
1773 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
1774 ha_alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
1775 file, linenum, args[0], errmsg);
1776 err_code |= ERR_ALERT | ERR_FATAL;
1777 free(expr);
1778 goto out;
1779 }
1780 }
1781 else if (*(args[myidx])) {
1782 ha_alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
1783 file, linenum, args[0], args[myidx]);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 free(expr);
1786 goto out;
1787 }
1788 if (flags & STK_ON_RSP)
1789 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
1790 else
1791 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1792
1793 rule = calloc(1, sizeof(*rule));
1794 rule->cond = cond;
1795 rule->expr = expr;
1796 rule->flags = flags;
1797 rule->table.name = name ? strdup(name) : NULL;
1798 LIST_INIT(&rule->list);
1799 if (flags & STK_ON_RSP)
1800 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
1801 else
1802 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
1803 }
1804 else if (!strcmp(args[0], "stats")) {
1805 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1806 curproxy->uri_auth = NULL; /* we must detach from the default config */
1807
1808 if (!*args[1]) {
1809 goto stats_error_parsing;
1810 } else if (!strcmp(args[1], "admin")) {
1811 struct stats_admin_rule *rule;
1812
1813 if (curproxy == &defproxy) {
1814 ha_alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
1819 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1820 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1821 err_code |= ERR_ALERT | ERR_ABORT;
1822 goto out;
1823 }
1824
1825 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1826 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1827 file, linenum, args[0], args[1]);
1828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
1830 }
1831 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1832 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
1833 file, linenum, args[0], args[1], errmsg);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
1838 err_code |= warnif_cond_conflicts(cond,
1839 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1840 file, linenum);
1841
1842 rule = calloc(1, sizeof(*rule));
1843 rule->cond = cond;
1844 LIST_INIT(&rule->list);
1845 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
1846 } else if (!strcmp(args[1], "uri")) {
1847 if (*(args[2]) == 0) {
1848 ha_alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1852 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1853 err_code |= ERR_ALERT | ERR_ABORT;
1854 goto out;
1855 }
1856 } else if (!strcmp(args[1], "realm")) {
1857 if (*(args[2]) == 0) {
1858 ha_alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1862 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1863 err_code |= ERR_ALERT | ERR_ABORT;
1864 goto out;
1865 }
1866 } else if (!strcmp(args[1], "refresh")) {
1867 unsigned interval;
1868
1869 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02001870 if (err == PARSE_TIME_OVER) {
1871 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to stats refresh interval, maximum value is 2147483647 s (~68 years).\n",
1872 file, linenum, args[2]);
1873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
1875 }
1876 else if (err == PARSE_TIME_UNDER) {
1877 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to stats refresh interval, minimum non-null value is 1 s.\n",
1878 file, linenum, args[2]);
1879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
1881 }
1882 else if (err) {
1883 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to stats refresh interval.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001884 file, linenum, *err);
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1888 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1889 err_code |= ERR_ALERT | ERR_ABORT;
1890 goto out;
1891 }
1892 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
1893 struct act_rule *rule;
1894
1895 if (curproxy == &defproxy) {
1896 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
1899 }
1900
1901 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1902 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1903 err_code |= ERR_ALERT | ERR_ABORT;
1904 goto out;
1905 }
1906
1907 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
1908 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
1909 ha_warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1910 file, linenum, args[0]);
1911 err_code |= ERR_WARN;
1912 }
1913
1914 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
1915
1916 if (!rule) {
1917 err_code |= ERR_ALERT | ERR_ABORT;
1918 goto out;
1919 }
1920
1921 err_code |= warnif_cond_conflicts(rule->cond,
1922 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1923 file, linenum);
1924 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
1925
1926 } else if (!strcmp(args[1], "auth")) {
1927 if (*(args[2]) == 0) {
1928 ha_alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
1931 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1932 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1933 err_code |= ERR_ALERT | ERR_ABORT;
1934 goto out;
1935 }
1936 } else if (!strcmp(args[1], "scope")) {
1937 if (*(args[2]) == 0) {
1938 ha_alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
1941 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1942 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1943 err_code |= ERR_ALERT | ERR_ABORT;
1944 goto out;
1945 }
1946 } else if (!strcmp(args[1], "enable")) {
1947 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1948 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1949 err_code |= ERR_ALERT | ERR_ABORT;
1950 goto out;
1951 }
1952 } else if (!strcmp(args[1], "hide-version")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001953 if (!stats_set_flag(&curproxy->uri_auth, STAT_HIDEVER)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001954 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1955 err_code |= ERR_ALERT | ERR_ABORT;
1956 goto out;
1957 }
1958 } else if (!strcmp(args[1], "show-legends")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001959 if (!stats_set_flag(&curproxy->uri_auth, STAT_SHLGNDS)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001960 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1961 err_code |= ERR_ALERT | ERR_ABORT;
1962 goto out;
1963 }
1964 } else if (!strcmp(args[1], "show-node")) {
1965
1966 if (*args[2]) {
1967 int i;
1968 char c;
1969
1970 for (i=0; args[2][i]; i++) {
1971 c = args[2][i];
1972 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1973 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
1974 break;
1975 }
1976
1977 if (!i || args[2][i]) {
1978 ha_alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1979 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1980 file, linenum, args[0], args[1]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984 }
1985
1986 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1987 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1988 err_code |= ERR_ALERT | ERR_ABORT;
1989 goto out;
1990 }
1991 } else if (!strcmp(args[1], "show-desc")) {
1992 char *desc = NULL;
1993
1994 if (*args[2]) {
1995 int i, len=0;
1996 char *d;
1997
1998 for (i = 2; *args[i]; i++)
1999 len += strlen(args[i]) + 1;
2000
2001 desc = d = calloc(1, len);
2002
2003 d += snprintf(d, desc + len - d, "%s", args[2]);
2004 for (i = 3; *args[i]; i++)
2005 d += snprintf(d, desc + len - d, " %s", args[i]);
2006 }
2007
2008 if (!*args[2] && !global.desc)
2009 ha_warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2010 file, linenum, args[1]);
2011 else {
2012 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2013 free(desc);
2014 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2015 err_code |= ERR_ALERT | ERR_ABORT;
2016 goto out;
2017 }
2018 free(desc);
2019 }
2020 } else {
2021stats_error_parsing:
2022 ha_alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2023 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
2024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
2027 }
2028 else if (!strcmp(args[0], "option")) {
2029 int optnum;
2030
2031 if (*(args[1]) == '\0') {
2032 ha_alert("parsing [%s:%d]: '%s' expects an option name.\n",
2033 file, linenum, args[0]);
2034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
2037
2038 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2039 if (!strcmp(args[1], cfg_opts[optnum].name)) {
2040 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
2041 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2042 file, linenum, cfg_opts[optnum].name);
2043 err_code |= ERR_ALERT | ERR_FATAL;
2044 goto out;
2045 }
2046 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2047 goto out;
2048
2049 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2050 err_code |= ERR_WARN;
2051 goto out;
2052 }
2053
2054 curproxy->no_options &= ~cfg_opts[optnum].val;
2055 curproxy->options &= ~cfg_opts[optnum].val;
2056
2057 switch (kwm) {
2058 case KWM_STD:
2059 curproxy->options |= cfg_opts[optnum].val;
2060 break;
2061 case KWM_NO:
2062 curproxy->no_options |= cfg_opts[optnum].val;
2063 break;
2064 case KWM_DEF: /* already cleared */
2065 break;
2066 }
2067
2068 goto out;
2069 }
2070 }
2071
2072 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2073 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
2074 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
2075 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2076 file, linenum, cfg_opts2[optnum].name);
2077 err_code |= ERR_ALERT | ERR_FATAL;
2078 goto out;
2079 }
2080 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2081 goto out;
2082 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2083 err_code |= ERR_WARN;
2084 goto out;
2085 }
2086
Christopher Faulet31930372019-07-15 10:16:58 +02002087 /* "[no] option http-use-htx" is deprecated */
2088 if (!strcmp(cfg_opts2[optnum].name, "http-use-htx")) {
Christopher Fauletf89f0992019-07-19 11:17:38 +02002089 if (kwm ==KWM_NO) {
2090 ha_warning("parsing [%s:%d]: option '%s' is deprecated and ignored."
2091 " The HTX mode is now the only supported mode.\n",
2092 file, linenum, cfg_opts2[optnum].name);
2093 err_code |= ERR_WARN;
2094 }
Christopher Faulet31930372019-07-15 10:16:58 +02002095 goto out;
2096 }
2097
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002098 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2099 curproxy->options2 &= ~cfg_opts2[optnum].val;
2100
2101 switch (kwm) {
2102 case KWM_STD:
2103 curproxy->options2 |= cfg_opts2[optnum].val;
2104 break;
2105 case KWM_NO:
2106 curproxy->no_options2 |= cfg_opts2[optnum].val;
2107 break;
2108 case KWM_DEF: /* already cleared */
2109 break;
2110 }
2111 goto out;
2112 }
2113 }
2114
2115 /* HTTP options override each other. They can be cancelled using
2116 * "no option xxx" which only switches to default mode if the mode
2117 * was this one (useful for cancelling options set in defaults
2118 * sections).
2119 */
2120 if (strcmp(args[1], "httpclose") == 0 || strcmp(args[1], "forceclose") == 0) {
Tim Duesterhus10c6c162019-05-14 20:58:00 +02002121 if (strcmp(args[1], "forceclose") == 0) {
2122 if (!already_warned(WARN_FORCECLOSE_DEPRECATED))
2123 ha_warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'httpclose', and will not be supported by future versions.\n",
2124 file, linenum, args[1]);
2125 err_code |= ERR_WARN;
2126 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002127 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2128 goto out;
2129 if (kwm == KWM_STD) {
2130 curproxy->options &= ~PR_O_HTTP_MODE;
2131 curproxy->options |= PR_O_HTTP_CLO;
2132 goto out;
2133 }
2134 else if (kwm == KWM_NO) {
2135 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO)
2136 curproxy->options &= ~PR_O_HTTP_MODE;
2137 goto out;
2138 }
2139 }
2140 else if (strcmp(args[1], "http-server-close") == 0) {
2141 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2142 goto out;
2143 if (kwm == KWM_STD) {
2144 curproxy->options &= ~PR_O_HTTP_MODE;
2145 curproxy->options |= PR_O_HTTP_SCL;
2146 goto out;
2147 }
2148 else if (kwm == KWM_NO) {
2149 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
2150 curproxy->options &= ~PR_O_HTTP_MODE;
2151 goto out;
2152 }
2153 }
2154 else if (strcmp(args[1], "http-keep-alive") == 0) {
2155 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2156 goto out;
2157 if (kwm == KWM_STD) {
2158 curproxy->options &= ~PR_O_HTTP_MODE;
2159 curproxy->options |= PR_O_HTTP_KAL;
2160 goto out;
2161 }
2162 else if (kwm == KWM_NO) {
2163 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
2164 curproxy->options &= ~PR_O_HTTP_MODE;
2165 goto out;
2166 }
2167 }
2168 else if (strcmp(args[1], "http-tunnel") == 0) {
Christopher Faulet73e8ede2019-07-16 15:04:46 +02002169 ha_warning("parsing [%s:%d]: the option '%s' is deprecated and will be removed in next version.\n",
2170 file, linenum, args[1]);
2171 err_code |= ERR_WARN;
2172 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002173 }
2174
2175 /* Redispatch can take an integer argument that control when the
2176 * resispatch occurs. All values are relative to the retries option.
2177 * This can be cancelled using "no option xxx".
2178 */
2179 if (strcmp(args[1], "redispatch") == 0) {
2180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
2181 err_code |= ERR_WARN;
2182 goto out;
2183 }
2184
2185 curproxy->no_options &= ~PR_O_REDISP;
2186 curproxy->options &= ~PR_O_REDISP;
2187
2188 switch (kwm) {
2189 case KWM_STD:
2190 curproxy->options |= PR_O_REDISP;
2191 curproxy->redispatch_after = -1;
2192 if(*args[2]) {
2193 curproxy->redispatch_after = atol(args[2]);
2194 }
2195 break;
2196 case KWM_NO:
2197 curproxy->no_options |= PR_O_REDISP;
2198 curproxy->redispatch_after = 0;
2199 break;
2200 case KWM_DEF: /* already cleared */
2201 break;
2202 }
2203 goto out;
2204 }
2205
2206 if (kwm != KWM_STD) {
2207 ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
2208 file, linenum, args[1]);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
2212
2213 if (!strcmp(args[1], "httplog")) {
2214 char *logformat;
2215 /* generate a complete HTTP log */
2216 logformat = default_http_log_format;
2217 if (*(args[2]) != '\0') {
2218 if (!strcmp(args[2], "clf")) {
2219 curproxy->options2 |= PR_O2_CLFLOG;
2220 logformat = clf_http_log_format;
2221 } else {
2222 ha_alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
2227 goto out;
2228 }
2229 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2230 char *oldlogformat = "log-format";
2231 char *clflogformat = "";
2232
2233 if (curproxy->conf.logformat_string == default_http_log_format)
2234 oldlogformat = "option httplog";
2235 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2236 oldlogformat = "option tcplog";
2237 else if (curproxy->conf.logformat_string == clf_http_log_format)
2238 oldlogformat = "option httplog clf";
2239 if (logformat == clf_http_log_format)
2240 clflogformat = " clf";
2241 ha_warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
2242 file, linenum, clflogformat, oldlogformat);
2243 }
2244 if (curproxy->conf.logformat_string != default_http_log_format &&
2245 curproxy->conf.logformat_string != default_tcp_log_format &&
2246 curproxy->conf.logformat_string != clf_http_log_format)
2247 free(curproxy->conf.logformat_string);
2248 curproxy->conf.logformat_string = logformat;
2249
2250 free(curproxy->conf.lfs_file);
2251 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2252 curproxy->conf.lfs_line = curproxy->conf.args.line;
2253
2254 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2255 ha_warning("parsing [%s:%d] : backend '%s' : 'option httplog' directive is ignored in backends.\n",
2256 file, linenum, curproxy->id);
2257 err_code |= ERR_WARN;
2258 }
2259 }
2260 else if (!strcmp(args[1], "tcplog")) {
2261 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2262 char *oldlogformat = "log-format";
2263
2264 if (curproxy->conf.logformat_string == default_http_log_format)
2265 oldlogformat = "option httplog";
2266 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2267 oldlogformat = "option tcplog";
2268 else if (curproxy->conf.logformat_string == clf_http_log_format)
2269 oldlogformat = "option httplog clf";
2270 ha_warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
2271 file, linenum, oldlogformat);
2272 }
2273 /* generate a detailed TCP log */
2274 if (curproxy->conf.logformat_string != default_http_log_format &&
2275 curproxy->conf.logformat_string != default_tcp_log_format &&
2276 curproxy->conf.logformat_string != clf_http_log_format)
2277 free(curproxy->conf.logformat_string);
2278 curproxy->conf.logformat_string = default_tcp_log_format;
2279
2280 free(curproxy->conf.lfs_file);
2281 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2282 curproxy->conf.lfs_line = curproxy->conf.args.line;
2283
2284 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2285 goto out;
2286
2287 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2288 ha_warning("parsing [%s:%d] : backend '%s' : 'option tcplog' directive is ignored in backends.\n",
2289 file, linenum, curproxy->id);
2290 err_code |= ERR_WARN;
2291 }
2292 }
2293 else if (!strcmp(args[1], "tcpka")) {
2294 /* enable TCP keep-alives on client and server streams */
2295 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
2296 err_code |= ERR_WARN;
2297
2298 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2299 goto out;
2300
2301 if (curproxy->cap & PR_CAP_FE)
2302 curproxy->options |= PR_O_TCP_CLI_KA;
2303 if (curproxy->cap & PR_CAP_BE)
2304 curproxy->options |= PR_O_TCP_SRV_KA;
2305 }
2306 else if (!strcmp(args[1], "httpchk")) {
2307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2308 err_code |= ERR_WARN;
2309
2310 /* use HTTP request to check servers' health */
2311 free(curproxy->check_req);
2312 curproxy->check_req = NULL;
2313 curproxy->options2 &= ~PR_O2_CHK_ANY;
2314 curproxy->options2 |= PR_O2_HTTP_CHK;
2315 if (!*args[2]) { /* no argument */
2316 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2317 curproxy->check_len = strlen(DEF_CHECK_REQ);
2318 } else if (!*args[3]) { /* one argument : URI */
2319 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
2320 curproxy->check_req = malloc(reqlen);
2321 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2322 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
2323 } else { /* more arguments : METHOD URI [HTTP_VER] */
2324 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
2325 if (*args[4])
2326 reqlen += strlen(args[4]);
2327 else
2328 reqlen += strlen("HTTP/1.0");
2329
2330 curproxy->check_req = malloc(reqlen);
2331 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2332 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2333 }
2334 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
2335 goto out;
2336 }
2337 else if (!strcmp(args[1], "ssl-hello-chk")) {
2338 /* use SSLv3 CLIENT HELLO to check servers' health */
2339 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2340 err_code |= ERR_WARN;
2341
2342 free(curproxy->check_req);
2343 curproxy->check_req = NULL;
2344 curproxy->options2 &= ~PR_O2_CHK_ANY;
2345 curproxy->options2 |= PR_O2_SSL3_CHK;
2346
2347 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2348 goto out;
2349 }
2350 else if (!strcmp(args[1], "smtpchk")) {
2351 /* use SMTP request to check servers' health */
2352 free(curproxy->check_req);
2353 curproxy->check_req = NULL;
2354 curproxy->options2 &= ~PR_O2_CHK_ANY;
2355 curproxy->options2 |= PR_O2_SMTP_CHK;
2356
2357 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2358 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2359 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2360 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2361 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2362 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2363 curproxy->check_req = malloc(reqlen);
2364 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2365 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2366 } else {
2367 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2368 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2369 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2370 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2371 }
2372 }
2373 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
2374 goto out;
2375 }
2376 else if (!strcmp(args[1], "pgsql-check")) {
2377 /* use PostgreSQL request to check servers' health */
2378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2379 err_code |= ERR_WARN;
2380
2381 free(curproxy->check_req);
2382 curproxy->check_req = NULL;
2383 curproxy->options2 &= ~PR_O2_CHK_ANY;
2384 curproxy->options2 |= PR_O2_PGSQL_CHK;
2385
2386 if (*(args[2])) {
2387 int cur_arg = 2;
2388
2389 while (*(args[cur_arg])) {
2390 if (strcmp(args[cur_arg], "user") == 0) {
2391 char * packet;
2392 uint32_t packet_len;
2393 uint32_t pv;
2394
2395 /* suboption header - needs additional argument for it */
2396 if (*(args[cur_arg+1]) == 0) {
2397 ha_alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
2398 file, linenum, args[0], args[1], args[cur_arg]);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402
2403 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
2404 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
2405 pv = htonl(0x30000); /* protocol version 3.0 */
2406
2407 packet = calloc(1, packet_len);
2408
2409 memcpy(packet + 4, &pv, 4);
2410
2411 /* copy "user" */
2412 memcpy(packet + 8, "user", 4);
2413
2414 /* copy username */
2415 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
2416
2417 free(curproxy->check_req);
2418 curproxy->check_req = packet;
2419 curproxy->check_len = packet_len;
2420
2421 packet_len = htonl(packet_len);
2422 memcpy(packet, &packet_len, 4);
2423 cur_arg += 2;
2424 } else {
2425 /* unknown suboption - catchall */
2426 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
2427 file, linenum, args[0], args[1]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431 } /* end while loop */
2432 }
2433 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
2434 goto out;
2435 }
2436
2437 else if (!strcmp(args[1], "redis-check")) {
2438 /* use REDIS PING request to check servers' health */
2439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2440 err_code |= ERR_WARN;
2441
2442 free(curproxy->check_req);
2443 curproxy->check_req = NULL;
2444 curproxy->options2 &= ~PR_O2_CHK_ANY;
2445 curproxy->options2 |= PR_O2_REDIS_CHK;
2446
2447 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
2448 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
2449 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
2450
2451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2452 goto out;
2453 }
2454
2455 else if (!strcmp(args[1], "mysql-check")) {
2456 /* use MYSQL request to check servers' health */
2457 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2458 err_code |= ERR_WARN;
2459
2460 free(curproxy->check_req);
2461 curproxy->check_req = NULL;
2462 curproxy->options2 &= ~PR_O2_CHK_ANY;
2463 curproxy->options2 |= PR_O2_MYSQL_CHK;
2464
2465 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
2466 * const char mysql40_client_auth_pkt[] = {
2467 * "\x0e\x00\x00" // packet length
2468 * "\x01" // packet number
2469 * "\x00\x00" // client capabilities
2470 * "\x00\x00\x01" // max packet
2471 * "haproxy\x00" // username (null terminated string)
2472 * "\x00" // filler (always 0x00)
2473 * "\x01\x00\x00" // packet length
2474 * "\x00" // packet number
2475 * "\x01" // COM_QUIT command
2476 * };
2477 */
2478
2479 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
2480 * const char mysql41_client_auth_pkt[] = {
2481 * "\x0e\x00\x00\" // packet length
2482 * "\x01" // packet number
2483 * "\x00\x00\x00\x00" // client capabilities
2484 * "\x00\x00\x00\x01" // max packet
2485 * "\x21" // character set (UTF-8)
2486 * char[23] // All zeroes
2487 * "haproxy\x00" // username (null terminated string)
2488 * "\x00" // filler (always 0x00)
2489 * "\x01\x00\x00" // packet length
2490 * "\x00" // packet number
2491 * "\x01" // COM_QUIT command
2492 * };
2493 */
2494
2495
2496 if (*(args[2])) {
2497 int cur_arg = 2;
2498
2499 while (*(args[cur_arg])) {
2500 if (strcmp(args[cur_arg], "user") == 0) {
2501 char *mysqluser;
2502 int packetlen, reqlen, userlen;
2503
2504 /* suboption header - needs additional argument for it */
2505 if (*(args[cur_arg+1]) == 0) {
2506 ha_alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
2507 file, linenum, args[0], args[1], args[cur_arg]);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511 mysqluser = args[cur_arg + 1];
2512 userlen = strlen(mysqluser);
2513
2514 if (*(args[cur_arg+2])) {
2515 if (!strcmp(args[cur_arg+2], "post-41")) {
2516 packetlen = userlen + 7 + 27;
2517 reqlen = packetlen + 9;
2518
2519 free(curproxy->check_req);
2520 curproxy->check_req = calloc(1, reqlen);
2521 curproxy->check_len = reqlen;
2522
2523 snprintf(curproxy->check_req, 4, "%c%c%c",
2524 ((unsigned char) packetlen & 0xff),
2525 ((unsigned char) (packetlen >> 8) & 0xff),
2526 ((unsigned char) (packetlen >> 16) & 0xff));
2527
2528 curproxy->check_req[3] = 1;
2529 curproxy->check_req[5] = 0x82; // 130
2530 curproxy->check_req[11] = 1;
2531 curproxy->check_req[12] = 33;
2532 memcpy(&curproxy->check_req[36], mysqluser, userlen);
2533 curproxy->check_req[36 + userlen + 1 + 1] = 1;
2534 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
2535 cur_arg += 3;
2536 } else {
2537 ha_alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
2538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
2540 }
2541 } else {
2542 packetlen = userlen + 7;
2543 reqlen = packetlen + 9;
2544
2545 free(curproxy->check_req);
2546 curproxy->check_req = calloc(1, reqlen);
2547 curproxy->check_len = reqlen;
2548
2549 snprintf(curproxy->check_req, 4, "%c%c%c",
2550 ((unsigned char) packetlen & 0xff),
2551 ((unsigned char) (packetlen >> 8) & 0xff),
2552 ((unsigned char) (packetlen >> 16) & 0xff));
2553
2554 curproxy->check_req[3] = 1;
2555 curproxy->check_req[5] = 0x80;
2556 curproxy->check_req[8] = 1;
2557 memcpy(&curproxy->check_req[9], mysqluser, userlen);
2558 curproxy->check_req[9 + userlen + 1 + 1] = 1;
2559 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
2560 cur_arg += 2;
2561 }
2562 } else {
2563 /* unknown suboption - catchall */
2564 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
2565 file, linenum, args[0], args[1]);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
2569 } /* end while loop */
2570 }
2571 }
2572 else if (!strcmp(args[1], "ldap-check")) {
2573 /* use LDAP request to check servers' health */
2574 free(curproxy->check_req);
2575 curproxy->check_req = NULL;
2576 curproxy->options2 &= ~PR_O2_CHK_ANY;
2577 curproxy->options2 |= PR_O2_LDAP_CHK;
2578
2579 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
2580 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
2581 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
2582 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2583 goto out;
2584 }
2585 else if (!strcmp(args[1], "spop-check")) {
2586 if (curproxy == &defproxy) {
2587 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
2588 file, linenum, args[0], args[1]);
2589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
2591 }
2592 if (curproxy->cap & PR_CAP_FE) {
2593 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
2594 file, linenum, args[0], args[1]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 /* use SPOE request to check servers' health */
2600 free(curproxy->check_req);
2601 curproxy->check_req = NULL;
2602 curproxy->options2 &= ~PR_O2_CHK_ANY;
2603 curproxy->options2 |= PR_O2_SPOP_CHK;
2604
2605 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
2606 ha_alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
2607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
2610 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2611 goto out;
2612 }
2613 else if (!strcmp(args[1], "tcp-check")) {
2614 /* use raw TCPCHK send/expect to check servers' health */
2615 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2616 err_code |= ERR_WARN;
2617
2618 free(curproxy->check_req);
2619 curproxy->check_req = NULL;
2620 curproxy->options2 &= ~PR_O2_CHK_ANY;
2621 curproxy->options2 |= PR_O2_TCPCHK_CHK;
2622 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2623 goto out;
2624 }
2625 else if (!strcmp(args[1], "external-check")) {
2626 /* excute an external command to check servers' health */
2627 free(curproxy->check_req);
2628 curproxy->check_req = NULL;
2629 curproxy->options2 &= ~PR_O2_CHK_ANY;
2630 curproxy->options2 |= PR_O2_EXT_CHK;
2631 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2632 goto out;
2633 }
2634 else if (!strcmp(args[1], "forwardfor")) {
2635 int cur_arg;
2636
2637 /* insert x-forwarded-for field, but not for the IP address listed as an except.
Christopher Faulet31930372019-07-15 10:16:58 +02002638 * set default options (ie: bitfield, header name, etc)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002639 */
2640
2641 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
2642
2643 free(curproxy->fwdfor_hdr_name);
2644 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2645 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2646
2647 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2648 cur_arg = 2;
2649 while (*(args[cur_arg])) {
2650 if (!strcmp(args[cur_arg], "except")) {
2651 /* suboption except - needs additional argument for it */
2652 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
2653 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2654 file, linenum, args[0], args[1], args[cur_arg]);
2655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
2657 }
2658 /* flush useless bits */
2659 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
2660 cur_arg += 2;
2661 } else if (!strcmp(args[cur_arg], "header")) {
2662 /* suboption header - needs additional argument for it */
2663 if (*(args[cur_arg+1]) == 0) {
2664 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2665 file, linenum, args[0], args[1], args[cur_arg]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669 free(curproxy->fwdfor_hdr_name);
2670 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2671 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2672 cur_arg += 2;
2673 } else if (!strcmp(args[cur_arg], "if-none")) {
2674 curproxy->options &= ~PR_O_FF_ALWAYS;
2675 cur_arg += 1;
2676 } else {
2677 /* unknown suboption - catchall */
2678 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
2679 file, linenum, args[0], args[1]);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683 } /* end while loop */
2684 }
2685 else if (!strcmp(args[1], "originalto")) {
2686 int cur_arg;
2687
2688 /* insert x-original-to field, but not for the IP address listed as an except.
2689 * set default options (ie: bitfield, header name, etc)
2690 */
2691
2692 curproxy->options |= PR_O_ORGTO;
2693
2694 free(curproxy->orgto_hdr_name);
2695 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2696 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2697
2698 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
2699 cur_arg = 2;
2700 while (*(args[cur_arg])) {
2701 if (!strcmp(args[cur_arg], "except")) {
2702 /* suboption except - needs additional argument for it */
2703 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
2704 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2705 file, linenum, args[0], args[1], args[cur_arg]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709 /* flush useless bits */
2710 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2711 cur_arg += 2;
2712 } else if (!strcmp(args[cur_arg], "header")) {
2713 /* suboption header - needs additional argument for it */
2714 if (*(args[cur_arg+1]) == 0) {
2715 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2716 file, linenum, args[0], args[1], args[cur_arg]);
2717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720 free(curproxy->orgto_hdr_name);
2721 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2722 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2723 cur_arg += 2;
2724 } else {
2725 /* unknown suboption - catchall */
2726 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2727 file, linenum, args[0], args[1]);
2728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
2730 }
2731 } /* end while loop */
2732 }
2733 else {
2734 ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 goto out;
2739 }
2740 else if (!strcmp(args[0], "default_backend")) {
2741 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2742 err_code |= ERR_WARN;
2743
2744 if (*(args[1]) == 0) {
2745 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
2746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749 free(curproxy->defbe.name);
2750 curproxy->defbe.name = strdup(args[1]);
2751
2752 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
2753 goto out;
2754 }
2755 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002756 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 +01002757
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002760 }
2761 else if (!strcmp(args[0], "http-reuse")) {
2762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2763 err_code |= ERR_WARN;
2764
2765 if (strcmp(args[1], "never") == 0) {
2766 /* enable a graceful server shutdown on an HTTP 404 response */
2767 curproxy->options &= ~PR_O_REUSE_MASK;
2768 curproxy->options |= PR_O_REUSE_NEVR;
2769 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2770 goto out;
2771 }
2772 else if (strcmp(args[1], "safe") == 0) {
2773 /* enable a graceful server shutdown on an HTTP 404 response */
2774 curproxy->options &= ~PR_O_REUSE_MASK;
2775 curproxy->options |= PR_O_REUSE_SAFE;
2776 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2777 goto out;
2778 }
2779 else if (strcmp(args[1], "aggressive") == 0) {
2780 curproxy->options &= ~PR_O_REUSE_MASK;
2781 curproxy->options |= PR_O_REUSE_AGGR;
2782 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2783 goto out;
2784 }
2785 else if (strcmp(args[1], "always") == 0) {
2786 /* enable a graceful server shutdown on an HTTP 404 response */
2787 curproxy->options &= ~PR_O_REUSE_MASK;
2788 curproxy->options |= PR_O_REUSE_ALWS;
2789 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2790 goto out;
2791 }
2792 else {
2793 ha_alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
2796 }
2797 }
2798 else if (!strcmp(args[0], "http-check")) {
2799 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2800 err_code |= ERR_WARN;
2801
2802 if (strcmp(args[1], "disable-on-404") == 0) {
2803 /* enable a graceful server shutdown on an HTTP 404 response */
2804 curproxy->options |= PR_O_DISABLE404;
2805 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2806 goto out;
2807 }
2808 else if (strcmp(args[1], "send-state") == 0) {
2809 /* enable emission of the apparent state of a server in HTTP checks */
2810 curproxy->options2 |= PR_O2_CHK_SNDST;
2811 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2812 goto out;
2813 }
2814 else if (strcmp(args[1], "expect") == 0) {
2815 const char *ptr_arg;
2816 int cur_arg;
2817
2818 if (curproxy->options2 & PR_O2_EXP_TYPE) {
2819 ha_alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823
2824 cur_arg = 2;
2825 /* consider exclamation marks, sole or at the beginning of a word */
2826 while (*(ptr_arg = args[cur_arg])) {
2827 while (*ptr_arg == '!') {
2828 curproxy->options2 ^= PR_O2_EXP_INV;
2829 ptr_arg++;
2830 }
2831 if (*ptr_arg)
2832 break;
2833 cur_arg++;
2834 }
2835 /* now ptr_arg points to the beginning of a word past any possible
2836 * exclamation mark, and cur_arg is the argument which holds this word.
2837 */
2838 if (strcmp(ptr_arg, "status") == 0) {
2839 if (!*(args[cur_arg + 1])) {
2840 ha_alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
2841 file, linenum, args[0], args[1], ptr_arg);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845 curproxy->options2 |= PR_O2_EXP_STS;
2846 free(curproxy->expect_str);
2847 curproxy->expect_str = strdup(args[cur_arg + 1]);
2848 }
2849 else if (strcmp(ptr_arg, "string") == 0) {
2850 if (!*(args[cur_arg + 1])) {
2851 ha_alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
2852 file, linenum, args[0], args[1], ptr_arg);
2853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
2856 curproxy->options2 |= PR_O2_EXP_STR;
2857 free(curproxy->expect_str);
2858 curproxy->expect_str = strdup(args[cur_arg + 1]);
2859 }
2860 else if (strcmp(ptr_arg, "rstatus") == 0) {
2861 if (!*(args[cur_arg + 1])) {
2862 ha_alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
2863 file, linenum, args[0], args[1], ptr_arg);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867 curproxy->options2 |= PR_O2_EXP_RSTS;
2868 free(curproxy->expect_str);
Dragan Dosen26743032019-04-30 15:54:36 +02002869 regex_free(curproxy->expect_regex);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002870 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002871 error = NULL;
Dragan Dosen26743032019-04-30 15:54:36 +02002872 if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
2873 ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002874 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
2875 free(error);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879 }
2880 else if (strcmp(ptr_arg, "rstring") == 0) {
2881 if (!*(args[cur_arg + 1])) {
2882 ha_alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
2883 file, linenum, args[0], args[1], ptr_arg);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887 curproxy->options2 |= PR_O2_EXP_RSTR;
2888 free(curproxy->expect_str);
Dragan Dosen26743032019-04-30 15:54:36 +02002889 regex_free(curproxy->expect_regex);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002890 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002891 error = NULL;
Dragan Dosen26743032019-04-30 15:54:36 +02002892 if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
2893 ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002894 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
2895 free(error);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899 }
2900 else {
2901 ha_alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
2902 file, linenum, args[0], args[1], ptr_arg);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906 }
2907 else {
2908 ha_alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912 }
2913 else if (!strcmp(args[0], "tcp-check")) {
2914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2915 err_code |= ERR_WARN;
2916
2917 if (strcmp(args[1], "comment") == 0) {
2918 int cur_arg;
2919 struct tcpcheck_rule *tcpcheck;
2920
2921 cur_arg = 1;
2922 tcpcheck = calloc(1, sizeof(*tcpcheck));
2923 tcpcheck->action = TCPCHK_ACT_COMMENT;
2924
2925 if (!*args[cur_arg + 1]) {
2926 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
2927 file, linenum, args[cur_arg]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931
2932 tcpcheck->comment = strdup(args[cur_arg + 1]);
2933
2934 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
2935 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
2936 goto out;
2937 }
2938 else if (strcmp(args[1], "connect") == 0) {
2939 const char *ptr_arg;
2940 int cur_arg;
2941 struct tcpcheck_rule *tcpcheck;
2942
2943 /* check if first rule is also a 'connect' action */
2944 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
2945 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
2946 tcpcheck->action == TCPCHK_ACT_COMMENT) {
2947 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
2948 }
2949
2950 if (&tcpcheck->list != &curproxy->tcpcheck_rules
2951 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
2952 ha_alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
2953 file, linenum);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957
2958 cur_arg = 2;
2959 tcpcheck = calloc(1, sizeof(*tcpcheck));
2960 tcpcheck->action = TCPCHK_ACT_CONNECT;
2961
2962 /* parsing each parameters to fill up the rule */
2963 while (*(ptr_arg = args[cur_arg])) {
2964 /* tcp port */
2965 if (strcmp(args[cur_arg], "port") == 0) {
2966 if ( (atol(args[cur_arg + 1]) > 65535) ||
2967 (atol(args[cur_arg + 1]) < 1) ){
2968 ha_alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
2969 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973 tcpcheck->port = atol(args[cur_arg + 1]);
2974 cur_arg += 2;
2975 }
2976 /* send proxy protocol */
2977 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
2978 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
2979 cur_arg++;
2980 }
2981#ifdef USE_OPENSSL
2982 else if (strcmp(args[cur_arg], "ssl") == 0) {
2983 curproxy->options |= PR_O_TCPCHK_SSL;
2984 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
2985 cur_arg++;
2986 }
2987#endif /* USE_OPENSSL */
2988 /* comment for this tcpcheck line */
2989 else if (strcmp(args[cur_arg], "comment") == 0) {
2990 if (!*args[cur_arg + 1]) {
2991 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
2992 file, linenum, args[cur_arg]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 tcpcheck->comment = strdup(args[cur_arg + 1]);
2997 cur_arg += 2;
2998 }
2999 else {
3000#ifdef USE_OPENSSL
3001 ha_alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
3002#else /* USE_OPENSSL */
3003 ha_alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
3004#endif /* USE_OPENSSL */
3005 file, linenum, args[0], args[1], args[cur_arg]);
3006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009
3010 }
3011
3012 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3013 }
3014 else if (strcmp(args[1], "send") == 0) {
3015 if (! *(args[2]) ) {
3016 /* SEND string expected */
3017 ha_alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
3018 file, linenum, args[0], args[1], args[2]);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 } else {
3022 struct tcpcheck_rule *tcpcheck;
3023
3024 tcpcheck = calloc(1, sizeof(*tcpcheck));
3025
3026 tcpcheck->action = TCPCHK_ACT_SEND;
3027 tcpcheck->string_len = strlen(args[2]);
3028 tcpcheck->string = strdup(args[2]);
3029 tcpcheck->expect_regex = NULL;
3030
3031 /* comment for this tcpcheck line */
3032 if (strcmp(args[3], "comment") == 0) {
3033 if (!*args[4]) {
3034 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
3035 file, linenum, args[3]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
3039 tcpcheck->comment = strdup(args[4]);
3040 }
3041
3042 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3043 }
3044 }
3045 else if (strcmp(args[1], "send-binary") == 0) {
3046 if (! *(args[2]) ) {
3047 /* SEND binary string expected */
3048 ha_alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
3049 file, linenum, args[0], args[1], args[2]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 } else {
3053 struct tcpcheck_rule *tcpcheck;
3054 char *err = NULL;
3055
3056 tcpcheck = calloc(1, sizeof(*tcpcheck));
3057
3058 tcpcheck->action = TCPCHK_ACT_SEND;
3059 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
3060 ha_alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
3061 file, linenum, args[0], args[1], args[2], err);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065 tcpcheck->expect_regex = NULL;
3066
3067 /* comment for this tcpcheck line */
3068 if (strcmp(args[3], "comment") == 0) {
3069 if (!*args[4]) {
3070 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
3071 file, linenum, args[3]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075 tcpcheck->comment = strdup(args[4]);
3076 }
3077
3078 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3079 }
3080 }
3081 else if (strcmp(args[1], "expect") == 0) {
3082 const char *ptr_arg;
3083 int cur_arg;
3084 int inverse = 0;
3085
3086 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3087 ha_alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
3091
3092 cur_arg = 2;
3093 /* consider exclamation marks, sole or at the beginning of a word */
3094 while (*(ptr_arg = args[cur_arg])) {
3095 while (*ptr_arg == '!') {
3096 inverse = !inverse;
3097 ptr_arg++;
3098 }
3099 if (*ptr_arg)
3100 break;
3101 cur_arg++;
3102 }
3103 /* now ptr_arg points to the beginning of a word past any possible
3104 * exclamation mark, and cur_arg is the argument which holds this word.
3105 */
3106 if (strcmp(ptr_arg, "binary") == 0) {
3107 struct tcpcheck_rule *tcpcheck;
3108 char *err = NULL;
3109
3110 if (!*(args[cur_arg + 1])) {
3111 ha_alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
3112 file, linenum, args[0], args[1], ptr_arg);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 tcpcheck = calloc(1, sizeof(*tcpcheck));
3118
3119 tcpcheck->action = TCPCHK_ACT_EXPECT;
3120 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
3121 ha_alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
3122 file, linenum, args[0], args[1], args[2], err);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126 tcpcheck->expect_regex = NULL;
3127 tcpcheck->inverse = inverse;
3128
3129 /* tcpcheck comment */
3130 cur_arg += 2;
3131 if (strcmp(args[cur_arg], "comment") == 0) {
3132 if (!*args[cur_arg + 1]) {
3133 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
3134 file, linenum, args[cur_arg + 1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138 tcpcheck->comment = strdup(args[cur_arg + 1]);
3139 }
3140
3141 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3142 }
3143 else if (strcmp(ptr_arg, "string") == 0) {
3144 struct tcpcheck_rule *tcpcheck;
3145
3146 if (!*(args[cur_arg + 1])) {
3147 ha_alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3148 file, linenum, args[0], args[1], ptr_arg);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152
3153 tcpcheck = calloc(1, sizeof(*tcpcheck));
3154
3155 tcpcheck->action = TCPCHK_ACT_EXPECT;
3156 tcpcheck->string_len = strlen(args[cur_arg + 1]);
3157 tcpcheck->string = strdup(args[cur_arg + 1]);
3158 tcpcheck->expect_regex = NULL;
3159 tcpcheck->inverse = inverse;
3160
3161 /* tcpcheck comment */
3162 cur_arg += 2;
3163 if (strcmp(args[cur_arg], "comment") == 0) {
3164 if (!*args[cur_arg + 1]) {
3165 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
3166 file, linenum, args[cur_arg + 1]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170 tcpcheck->comment = strdup(args[cur_arg + 1]);
3171 }
3172
3173 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3174 }
3175 else if (strcmp(ptr_arg, "rstring") == 0) {
3176 struct tcpcheck_rule *tcpcheck;
3177
3178 if (!*(args[cur_arg + 1])) {
3179 ha_alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3180 file, linenum, args[0], args[1], ptr_arg);
3181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
3183 }
3184
3185 tcpcheck = calloc(1, sizeof(*tcpcheck));
3186
3187 tcpcheck->action = TCPCHK_ACT_EXPECT;
3188 tcpcheck->string_len = 0;
3189 tcpcheck->string = NULL;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003190 error = NULL;
Dragan Dosen26743032019-04-30 15:54:36 +02003191 if (!(tcpcheck->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
3192 ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003193 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
3194 free(error);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
3198 tcpcheck->inverse = inverse;
3199
3200 /* tcpcheck comment */
3201 cur_arg += 2;
3202 if (strcmp(args[cur_arg], "comment") == 0) {
3203 if (!*args[cur_arg + 1]) {
3204 ha_alert("parsing [%s:%d] : '%s' expects a comment string.\n",
3205 file, linenum, args[cur_arg + 1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209 tcpcheck->comment = strdup(args[cur_arg + 1]);
3210 }
3211
3212 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
3213 }
3214 else {
3215 ha_alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
3216 file, linenum, args[0], args[1], ptr_arg);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
3220 }
3221 else {
3222 ha_alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
3226 }
3227 else if (!strcmp(args[0], "monitor")) {
3228 if (curproxy == &defproxy) {
3229 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
3232 }
3233
3234 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
3235 err_code |= ERR_WARN;
3236
3237 if (strcmp(args[1], "fail") == 0) {
3238 /* add a condition to fail monitor requests */
3239 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3240 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3241 file, linenum, args[0], args[1]);
3242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
3244 }
3245
3246 err_code |= warnif_misplaced_monitor(curproxy, file, linenum, "monitor fail");
3247 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3248 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3249 file, linenum, args[0], args[1], errmsg);
3250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
3252 }
3253 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3254 }
3255 else {
3256 ha_alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 }
Willy Tarreaue5733232019-05-22 19:24:06 +02003261#ifdef USE_TPROXY
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003262 else if (!strcmp(args[0], "transparent")) {
3263 /* enable transparent proxy connections */
3264 curproxy->options |= PR_O_TRANSP;
3265 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3266 goto out;
3267 }
3268#endif
3269 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
3270 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
3271 err_code |= ERR_WARN;
3272
3273 if (*(args[1]) == 0) {
3274 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277 }
3278 curproxy->maxconn = atol(args[1]);
3279 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3280 goto out;
3281 }
3282 else if (!strcmp(args[0], "backlog")) { /* backlog */
3283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
3284 err_code |= ERR_WARN;
3285
3286 if (*(args[1]) == 0) {
3287 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290 }
3291 curproxy->backlog = atol(args[1]);
3292 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3293 goto out;
3294 }
3295 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
3296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
3297 err_code |= ERR_WARN;
3298
3299 if (*(args[1]) == 0) {
3300 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
3301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
3303 }
3304 curproxy->fullconn = atol(args[1]);
3305 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3306 goto out;
3307 }
3308 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3309 if (*(args[1]) == 0) {
3310 ha_alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +02003315 if (err == PARSE_TIME_OVER) {
3316 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to grace time, maximum value is 2147483647 ms (~24.8 days).\n",
3317 file, linenum, args[1]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321 else if (err == PARSE_TIME_UNDER) {
3322 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to grace time, minimum non-null value is 1 ms.\n",
3323 file, linenum, args[1]);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
3327 else if (err) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003328 ha_alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3329 file, linenum, *err);
3330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
3332 }
3333 curproxy->grace = val;
3334 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3335 goto out;
3336 }
3337 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
3338 struct sockaddr_storage *sk;
3339 int port1, port2;
3340 struct protocol *proto;
3341
3342 if (curproxy == &defproxy) {
3343 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346 }
3347 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3348 err_code |= ERR_WARN;
3349
3350 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
3351 if (!sk) {
3352 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 proto = protocol_by_family(sk->ss_family);
3358 if (!proto || !proto->connect) {
3359 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3360 file, linenum, args[0], args[1]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364
3365 if (port1 != port2) {
3366 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3367 file, linenum, args[0], args[1]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371
3372 if (!port1) {
3373 ha_alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3374 file, linenum, args[0], args[1]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
3378
3379 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3380 goto out;
3381
3382 curproxy->dispatch_addr = *sk;
3383 curproxy->options |= PR_O_DISPATCH;
3384 }
3385 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3387 err_code |= ERR_WARN;
3388
3389 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3390 ha_alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394 }
3395 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3396 /**
3397 * The syntax for hash-type config element is
3398 * hash-type {map-based|consistent} [[<algo>] avalanche]
3399 *
3400 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
3401 */
3402 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
3403
3404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3405 err_code |= ERR_WARN;
3406
3407 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3408 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3409 }
3410 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3411 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3412 }
3413 else if (strcmp(args[1], "avalanche") == 0) {
3414 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]);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
3418 else {
3419 ha_alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
3422 }
3423
3424 /* set the hash function to use */
3425 if (!*args[2]) {
3426 /* the default algo is sdbm */
3427 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
3428
3429 /* if consistent with no argument, then avalanche modifier is also applied */
3430 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
3431 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
3432 } else {
3433 /* set the hash function */
3434 if (!strcmp(args[2], "sdbm")) {
3435 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
3436 }
3437 else if (!strcmp(args[2], "djb2")) {
3438 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
3439 }
3440 else if (!strcmp(args[2], "wt6")) {
3441 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
3442 }
3443 else if (!strcmp(args[2], "crc32")) {
3444 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
3445 }
3446 else {
3447 ha_alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451
3452 /* set the hash modifier */
3453 if (!strcmp(args[3], "avalanche")) {
3454 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
3455 }
3456 else if (*args[3]) {
3457 ha_alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461 }
3462 }
3463 else if (strcmp(args[0], "hash-balance-factor") == 0) {
3464 if (*(args[1]) == 0) {
3465 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
Willy Tarreau76e84f52019-01-14 16:50:58 +01003469 curproxy->lbprm.hash_balance_factor = atol(args[1]);
3470 if (curproxy->lbprm.hash_balance_factor != 0 && curproxy->lbprm.hash_balance_factor <= 100) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003471 ha_alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475 }
3476 else if (strcmp(args[0], "unique-id-format") == 0) {
3477 if (!*(args[1])) {
3478 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482 if (*(args[2])) {
3483 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487 free(curproxy->conf.uniqueid_format_string);
3488 curproxy->conf.uniqueid_format_string = strdup(args[1]);
3489
3490 free(curproxy->conf.uif_file);
3491 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
3492 curproxy->conf.uif_line = curproxy->conf.args.line;
3493 }
3494
3495 else if (strcmp(args[0], "unique-id-header") == 0) {
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01003496 char *copy;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003497 if (!*(args[1])) {
3498 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01003502 copy = strdup(args[1]);
3503 if (copy == NULL) {
3504 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
3505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
3507 }
3508
3509 istfree(&curproxy->header_unique_id);
3510 curproxy->header_unique_id = ist(copy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003511 }
3512
3513 else if (strcmp(args[0], "log-format") == 0) {
3514 if (!*(args[1])) {
3515 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 if (*(args[2])) {
3520 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
3525 char *oldlogformat = "log-format";
3526
3527 if (curproxy->conf.logformat_string == default_http_log_format)
3528 oldlogformat = "option httplog";
3529 else if (curproxy->conf.logformat_string == default_tcp_log_format)
3530 oldlogformat = "option tcplog";
3531 else if (curproxy->conf.logformat_string == clf_http_log_format)
3532 oldlogformat = "option httplog clf";
3533 ha_warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
3534 file, linenum, oldlogformat);
3535 }
3536 if (curproxy->conf.logformat_string != default_http_log_format &&
3537 curproxy->conf.logformat_string != default_tcp_log_format &&
3538 curproxy->conf.logformat_string != clf_http_log_format)
3539 free(curproxy->conf.logformat_string);
3540 curproxy->conf.logformat_string = strdup(args[1]);
3541
3542 free(curproxy->conf.lfs_file);
3543 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3544 curproxy->conf.lfs_line = curproxy->conf.args.line;
3545
3546 /* get a chance to improve log-format error reporting by
3547 * reporting the correct line-number when possible.
3548 */
3549 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
3550 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
3551 file, linenum, curproxy->id);
3552 err_code |= ERR_WARN;
3553 }
3554 }
3555 else if (!strcmp(args[0], "log-format-sd")) {
3556 if (!*(args[1])) {
3557 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561 if (*(args[2])) {
3562 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566
3567 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
3568 free(curproxy->conf.logformat_sd_string);
3569 curproxy->conf.logformat_sd_string = strdup(args[1]);
3570
3571 free(curproxy->conf.lfsd_file);
3572 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
3573 curproxy->conf.lfsd_line = curproxy->conf.args.line;
3574
3575 /* get a chance to improve log-format-sd error reporting by
3576 * reporting the correct line-number when possible.
3577 */
3578 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
3579 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
3580 file, linenum, curproxy->id);
3581 err_code |= ERR_WARN;
3582 }
3583 }
3584 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
3585 if (*(args[1]) == 0) {
3586 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 chunk_destroy(&curproxy->log_tag);
3591 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
3592 }
3593 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
3594 if (!parse_logsrv(args, &curproxy->logsrvs, (kwm == KWM_NO), &errmsg)) {
3595 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 }
3600 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
3601 int cur_arg;
3602 int port1, port2;
3603 struct sockaddr_storage *sk;
3604 struct protocol *proto;
3605
3606 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3607 err_code |= ERR_WARN;
3608
3609 if (!*args[1]) {
3610 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3611 file, linenum, "source", "usesrc", "interface");
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615
Christopher Faulet31930372019-07-15 10:16:58 +02003616 /* we must first clear any optional default setting */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003617 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
3618 free(curproxy->conn_src.iface_name);
3619 curproxy->conn_src.iface_name = NULL;
3620 curproxy->conn_src.iface_len = 0;
3621
3622 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
3623 if (!sk) {
3624 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
3625 file, linenum, args[0], args[1], errmsg);
3626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
3628 }
3629
3630 proto = protocol_by_family(sk->ss_family);
3631 if (!proto || !proto->connect) {
3632 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3633 file, linenum, args[0], args[1]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637
3638 if (port1 != port2) {
3639 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
3640 file, linenum, args[0], args[1]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644
3645 curproxy->conn_src.source_addr = *sk;
3646 curproxy->conn_src.opts |= CO_SRC_BIND;
3647
3648 cur_arg = 2;
3649 while (*(args[cur_arg])) {
3650 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
3651#if defined(CONFIG_HAP_TRANSPARENT)
3652 if (!*args[cur_arg + 1]) {
3653 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3654 file, linenum, "usesrc");
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658
3659 if (!strcmp(args[cur_arg + 1], "client")) {
3660 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
3661 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
3662 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3663 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
3664 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
3665 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3666 char *name, *end;
3667
3668 name = args[cur_arg+1] + 7;
Willy Tarreau90807112020-02-25 08:16:33 +01003669 while (isspace((unsigned char)*name))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003670 name++;
3671
3672 end = name;
Willy Tarreau90807112020-02-25 08:16:33 +01003673 while (*end && !isspace((unsigned char)*end) && *end != ',' && *end != ')')
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003674 end++;
3675
3676 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
3677 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
3678 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
3679 curproxy->conn_src.bind_hdr_len = end - name;
3680 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
3681 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
3682 curproxy->conn_src.bind_hdr_occ = -1;
3683
3684 /* now look for an occurrence number */
Willy Tarreau90807112020-02-25 08:16:33 +01003685 while (isspace((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003686 end++;
3687 if (*end == ',') {
3688 end++;
3689 name = end;
3690 if (*end == '-')
3691 end++;
Willy Tarreau90807112020-02-25 08:16:33 +01003692 while (isdigit((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003693 end++;
3694 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
3695 }
3696
3697 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
3698 ha_alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3699 " occurrences values smaller than %d.\n",
3700 file, linenum, MAX_HDR_HISTORY);
3701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
3703 }
3704 } else {
3705 struct sockaddr_storage *sk;
3706
3707 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
3708 if (!sk) {
3709 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
3710 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
3714
3715 proto = protocol_by_family(sk->ss_family);
3716 if (!proto || !proto->connect) {
3717 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3718 file, linenum, args[cur_arg], args[cur_arg+1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722
3723 if (port1 != port2) {
3724 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
3725 file, linenum, args[cur_arg], args[cur_arg + 1]);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
3729 curproxy->conn_src.tproxy_addr = *sk;
3730 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
3731 }
3732 global.last_checks |= LSTCHK_NETADM;
3733#else /* no TPROXY support */
3734 ha_alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
3735 file, linenum, "usesrc");
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
3738#endif
3739 cur_arg += 2;
3740 continue;
3741 }
3742
3743 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3744#ifdef SO_BINDTODEVICE
3745 if (!*args[cur_arg + 1]) {
3746 ha_alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3747 file, linenum, args[0]);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751 free(curproxy->conn_src.iface_name);
3752 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
3753 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
3754 global.last_checks |= LSTCHK_NETADM;
3755#else
3756 ha_alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3757 file, linenum, args[0], args[cur_arg]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760#endif
3761 cur_arg += 2;
3762 continue;
3763 }
3764 ha_alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3765 file, linenum, args[0], "interface", "usesrc");
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769 }
3770 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3771 ha_alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3772 file, linenum, "usesrc", "source");
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
3776 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003777 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Willy Tarreau262c3f12019-12-17 06:52:51 +01003778 "Use 'http-request replace-path', 'http-request replace-uri' or 'http-request replace-header' instead.\n",
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003779 file, linenum, args[0]);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003782 }
3783 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003784 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3785 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
3786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003788 }
3789 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003790 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1. "
3791 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003794 }
3795 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003796 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003799 }
3800 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003801 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3802 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003805 }
3806 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003807 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3808 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003811 }
3812 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003813 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3814 "Use 'http-request replace-header' instead.\n", file, linenum, args[0]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003817 }
3818 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003819 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3820 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003823 }
3824 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003825 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3826 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003829 }
3830 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003831 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003834 }
3835 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003836 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3837 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003840 }
3841 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003842 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3843 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003846 }
3847 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003848 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3849 "Use 'http-request add-header' instead.\n", file, linenum, args[0]);
3850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003852 }
3853 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003854 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3855 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003858 }
3859 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003860 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3861 "Use 'http-response del-header' .\n", file, linenum, args[0]);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003864 }
3865 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003866 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3867 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
3868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003870 }
3871 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Balvinder Singh Rawatdef595e2020-03-14 12:11:50 +05303872 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003873 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003876 }
3877 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003878 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3879 "Use 'http-response del-header' instead.\n", file, linenum, args[0]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003882 }
3883 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003884 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3885 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003888 }
3889 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003890 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3891 "Use 'http-response add-header' instead.\n", file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003894 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003895 else {
3896 struct cfg_kw_list *kwl;
3897 int index;
3898
3899 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3900 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3901 if (kwl->kw[index].section != CFG_LISTEN)
3902 continue;
3903 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3904 /* prepare error message just in case */
3905 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
3906 if (rc < 0) {
3907 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
3911 else if (rc > 0) {
3912 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3913 err_code |= ERR_WARN;
3914 goto out;
3915 }
3916 goto out;
3917 }
3918 }
3919 }
3920
3921 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925 out:
3926 free(errmsg);
3927 return err_code;
3928}