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