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