blob: 176025933ec1b375d0c0067e70f5964483a89374 [file] [log] [blame]
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <netdb.h>
5#include <ctype.h>
6#include <pwd.h>
7#include <grp.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include <unistd.h>
13
Willy Tarreaudcc048a2020-06-04 19:11:43 +020014#include <haproxy/acl.h>
Eric Salama7cea6062020-10-02 11:58:19 +020015#include <haproxy/buf.h>
Willy Tarreau278161c2020-06-04 11:18:28 +020016#include <haproxy/capture-t.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020017#include <haproxy/cfgparse.h>
Willy Tarreau4aa573d2020-06-04 18:21:56 +020018#include <haproxy/check.h>
Willy Tarreau0a3bd392020-06-04 08:52:38 +020019#include <haproxy/compression-t.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020020#include <haproxy/connection.h>
Willy Tarreaubcc67332020-06-05 15:31:31 +020021#include <haproxy/extcheck.h>
Willy Tarreau87735332020-06-04 09:08:41 +020022#include <haproxy/http_htx.h>
Willy Tarreauc761f842020-06-04 11:40:28 +020023#include <haproxy/http_rules.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020024#include <haproxy/listener.h>
Willy Tarreau36979d92020-06-05 17:27:29 +020025#include <haproxy/log.h>
Willy Tarreau872f2ea2020-06-04 18:46:44 +020026#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020027#include <haproxy/protocol.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 Tarreau872f2ea2020-06-04 18:46:44 +020032#include <haproxy/stick_table.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020033#include <haproxy/tcpcheck.h>
34#include <haproxy/uri_auth.h>
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010035
Willy Tarreau7d0c1432021-02-12 12:29:28 +010036
37static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
38
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010039/* Report a warning if a rule is placed after a 'tcp-request session' rule.
40 * Return 1 if the warning has been emitted, otherwise 0.
41 */
42int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
43{
44 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
45 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
46 file, line, arg);
47 return 1;
48 }
49 return 0;
50}
51
52/* Report a warning if a rule is placed after a 'tcp-request content' rule.
53 * Return 1 if the warning has been emitted, otherwise 0.
54 */
55int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
56{
57 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
58 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
59 file, line, arg);
60 return 1;
61 }
62 return 0;
63}
64
65/* Report a warning if a rule is placed after a 'monitor fail' rule.
66 * Return 1 if the warning has been emitted, otherwise 0.
67 */
68int warnif_rule_after_monitor(struct proxy *proxy, const char *file, int line, const char *arg)
69{
70 if (!LIST_ISEMPTY(&proxy->mon_fail_cond)) {
71 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'monitor fail' rule will still be processed before.\n",
72 file, line, arg);
73 return 1;
74 }
75 return 0;
76}
77
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010078/* Report a warning if a rule is placed after an 'http_request' rule.
79 * Return 1 if the warning has been emitted, otherwise 0.
80 */
81int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
82{
83 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
84 ha_warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
85 file, line, arg);
86 return 1;
87 }
88 return 0;
89}
90
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010091/* Report a warning if a rule is placed after a redirect rule.
92 * Return 1 if the warning has been emitted, otherwise 0.
93 */
94int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
95{
96 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
97 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
98 file, line, arg);
99 return 1;
100 }
101 return 0;
102}
103
104/* Report a warning if a rule is placed after a 'use_backend' rule.
105 * Return 1 if the warning has been emitted, otherwise 0.
106 */
107int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
108{
109 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
110 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
111 file, line, arg);
112 return 1;
113 }
114 return 0;
115}
116
117/* Report a warning if a rule is placed after a 'use-server' rule.
118 * Return 1 if the warning has been emitted, otherwise 0.
119 */
120int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
121{
122 if (!LIST_ISEMPTY(&proxy->server_rules)) {
123 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
124 file, line, arg);
125 return 1;
126 }
127 return 0;
128}
129
130/* report a warning if a redirect rule is dangerously placed */
131int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
132{
133 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
134 warnif_rule_after_use_server(proxy, file, line, arg);
135}
136
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100137/* report a warning if an http-request rule is dangerously placed */
138int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
139{
Christopher Faulet1b6adb42019-07-17 15:33:14 +0200140 return warnif_rule_after_redirect(proxy, file, line, arg) ||
141 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100142}
143
144/* report a warning if a block rule is dangerously placed */
Christopher Faulet8c3b63a2019-07-17 15:19:51 +0200145int warnif_misplaced_monitor(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100146{
147 return warnif_rule_after_http_req(proxy, file, line, arg) ||
148 warnif_misplaced_http_req(proxy, file, line, arg);
149}
150
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100151/* report a warning if a "tcp request content" rule is dangerously placed */
152int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
153{
154 return warnif_rule_after_monitor(proxy, file, line, arg) ||
155 warnif_misplaced_monitor(proxy, file, line, arg);
156}
157
158/* report a warning if a "tcp request session" rule is dangerously placed */
159int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
160{
161 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
162 warnif_misplaced_tcp_cont(proxy, file, line, arg);
163}
164
165/* report a warning if a "tcp request connection" rule is dangerously placed */
166int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
167{
168 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
169 warnif_misplaced_tcp_sess(proxy, file, line, arg);
170}
171
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100172int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
173{
174 static struct proxy *curproxy = NULL;
175 const char *err;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100176 int rc;
177 unsigned val;
178 int err_code = 0;
179 struct acl_cond *cond = NULL;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100180 char *errmsg = NULL;
181 struct bind_conf *bind_conf;
182
Willy Tarreau7d0c1432021-02-12 12:29:28 +0100183 if (defproxy.obj_type != OBJ_TYPE_PROXY) {
184 /* defproxy not initialized yet */
185 init_new_proxy(&defproxy);
186 proxy_preset_defaults(&defproxy);
187 }
188
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100189 if (strcmp(args[0], "listen") == 0)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100190 rc = PR_CAP_LISTEN;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100191 else if (strcmp(args[0], "frontend") == 0)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100192 rc = PR_CAP_FE;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100193 else if (strcmp(args[0], "backend") == 0)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100194 rc = PR_CAP_BE;
Willy Tarreau80dc6fe2021-02-12 09:43:33 +0100195 else if (strcmp(args[0], "defaults") == 0)
196 rc = PR_CAP_DEF;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100197 else
198 rc = PR_CAP_NONE;
199
Willy Tarreau80dc6fe2021-02-12 09:43:33 +0100200 if (rc & PR_CAP_LISTEN) { /* new proxy */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100201 if (!*args[1]) {
Willy Tarreaub2ec9942021-02-12 13:28:22 +0100202 ha_alert("parsing [%s:%d] : '%s' expects an <id> argument\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100203 file, linenum, args[0]);
204 err_code |= ERR_ALERT | ERR_ABORT;
205 goto out;
206 }
207
208 err = invalid_char(args[1]);
209 if (err) {
210 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
211 file, linenum, *err, args[0], args[1]);
212 err_code |= ERR_ALERT | ERR_FATAL;
213 }
214
215 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
216 if (curproxy) {
217 ha_alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
218 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
219 curproxy->id, curproxy->conf.file, curproxy->conf.line);
220 err_code |= ERR_ALERT | ERR_FATAL;
221 }
222
Emeric Brunb0c331f2020-10-07 17:05:59 +0200223 curproxy = log_forward_by_name(args[1]);
224 if (curproxy) {
225 ha_alert("Parsing [%s:%d]: %s '%s' has the same name as log forward section '%s' declared at %s:%d.\n",
226 file, linenum, proxy_cap_str(rc), args[1],
227 curproxy->id, curproxy->conf.file, curproxy->conf.line);
228 err_code |= ERR_ALERT | ERR_FATAL;
229 }
230
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100231 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
Willy Tarreau76838932021-02-12 08:49:47 +0100232 if (rc & PR_CAP_FE)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100233 ha_alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
234 goto out;
235 }
236
Willy Tarreau76838932021-02-12 08:49:47 +0100237 curproxy = alloc_new_proxy(args[1], rc, file, linenum, &defproxy, &errmsg);
238 if (!curproxy) {
239 /* message already printed by alloc_new_proxy() */
240 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
241 err_code |= ERR_ALERT | ERR_ABORT;
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100242 goto out;
243 }
Willy Tarreau76838932021-02-12 08:49:47 +0100244 curproxy->next = proxies_list;
245 proxies_list = curproxy;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100246
247 goto out;
248 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100249 else if (strcmp(args[0], "defaults") == 0) { /* use this one to assign default values */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100250 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
251 err_code |= ERR_ABORT;
252 goto out;
253 }
254
Willy Tarreaua3320a02021-02-12 10:38:49 +0100255 /* let's first free previous defaults */
256 proxy_free_defaults(&defproxy);
Willy Tarreau144289b2021-02-12 08:19:01 +0100257 init_new_proxy(&defproxy);
258 proxy_preset_defaults(&defproxy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100259 curproxy = &defproxy;
260 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
261 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau80dc6fe2021-02-12 09:43:33 +0100262 defproxy.cap = PR_CAP_DEF | PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100263 goto out;
264 }
265 else if (curproxy == NULL) {
266 ha_alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
267 err_code |= ERR_ALERT | ERR_FATAL;
268 goto out;
269 }
270
271 /* update the current file and line being parsed */
272 curproxy->conf.args.file = curproxy->conf.file;
273 curproxy->conf.args.line = linenum;
274
275 /* Now let's parse the proxy-specific keywords */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100276 if (strcmp(args[0], "server") == 0 ||
277 strcmp(args[0], "default-server") == 0 ||
278 strcmp(args[0], "server-template") == 0) {
Emeric Brund3db3842020-07-21 16:54:36 +0200279 err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1, 0, 0);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100280 if (err_code & ERR_FATAL)
281 goto out;
282 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100283 else if (strcmp(args[0], "bind") == 0) { /* new listen addresses */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100284 struct listener *l;
285 int cur_arg;
286
287 if (curproxy == &defproxy) {
288 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
289 err_code |= ERR_ALERT | ERR_FATAL;
290 goto out;
291 }
292 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
293 err_code |= ERR_WARN;
294
295 if (!*(args[1])) {
296 ha_alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
297 file, linenum, args[0]);
298 err_code |= ERR_ALERT | ERR_FATAL;
299 goto out;
300 }
301
302 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
303
304 /* use default settings for unix sockets */
Willy Tarreau6e459d72020-09-03 07:09:09 +0200305 bind_conf->settings.ux.uid = global.unix_bind.ux.uid;
306 bind_conf->settings.ux.gid = global.unix_bind.ux.gid;
307 bind_conf->settings.ux.mode = global.unix_bind.ux.mode;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100308
309 /* NOTE: the following line might create several listeners if there
310 * are comma-separated IPs or port ranges. So all further processing
311 * will have to be applied to all listeners created after last_listen.
312 */
313 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
314 if (errmsg && *errmsg) {
315 indent_msg(&errmsg, 2);
316 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
317 }
318 else
319 ha_alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
320 file, linenum, args[0], args[1]);
321 err_code |= ERR_ALERT | ERR_FATAL;
322 goto out;
323 }
324
325 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
326 /* Set default global rights and owner for unix bind */
327 global.maxsock++;
328 }
329
330 cur_arg = 2;
331 while (*(args[cur_arg])) {
332 static int bind_dumped;
333 struct bind_kw *kw;
334 char *err;
335
336 kw = bind_find_kw(args[cur_arg]);
337 if (kw) {
338 char *err = NULL;
339 int code;
340
341 if (!kw->parse) {
342 ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
343 file, linenum, args[0], args[1], args[cur_arg]);
344 cur_arg += 1 + kw->skip ;
345 err_code |= ERR_ALERT | ERR_FATAL;
346 goto out;
347 }
348
349 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
350 err_code |= code;
351
352 if (code) {
353 if (err && *err) {
354 indent_msg(&err, 2);
Emeric Brun0655c9b2019-10-17 16:45:56 +0200355 if (((code & (ERR_WARN|ERR_ALERT)) == ERR_WARN))
356 ha_warning("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
357 else
358 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100359 }
360 else
361 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
362 file, linenum, args[0], args[1], args[cur_arg]);
363 if (code & ERR_FATAL) {
364 free(err);
365 cur_arg += 1 + kw->skip;
366 goto out;
367 }
368 }
369 free(err);
370 cur_arg += 1 + kw->skip;
371 continue;
372 }
373
374 err = NULL;
375 if (!bind_dumped) {
376 bind_dump_kws(&err);
377 indent_msg(&err, 4);
378 bind_dumped = 1;
379 }
380
381 ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
382 file, linenum, args[0], args[1], args[cur_arg],
383 err ? " Registered keywords :" : "", err ? err : "");
384 free(err);
385
386 err_code |= ERR_ALERT | ERR_FATAL;
387 goto out;
388 }
389 goto out;
390 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100391 else if (strcmp(args[0], "monitor-net") == 0) { /* set the range of IPs to ignore */
Willy Tarreau9e9919d2020-10-14 15:55:23 +0200392 ha_alert("parsing [%s:%d] : 'monitor-net' doesn't exist anymore. Please use 'http-request return status 200 if { src %s }' instead.\n", file, linenum, args[1]);
393 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100394 goto out;
395 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100396 else if (strcmp(args[0], "monitor-uri") == 0) { /* set the URI to intercept */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100397 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
398 err_code |= ERR_WARN;
399
400 if (alertif_too_many_args(1, file, linenum, args, &err_code))
401 goto out;
402
403 if (!*args[1]) {
404 ha_alert("parsing [%s:%d] : '%s' expects an URI.\n",
405 file, linenum, args[0]);
406 err_code |= ERR_ALERT | ERR_FATAL;
407 goto out;
408 }
409
410 free(curproxy->monitor_uri);
411 curproxy->monitor_uri_len = strlen(args[1]);
412 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
413 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
414 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
415
416 goto out;
417 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100418 else if (strcmp(args[0], "mode") == 0) { /* sets the proxy mode */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100419 if (alertif_too_many_args(1, file, linenum, args, &err_code))
420 goto out;
421
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100422 if (strcmp(args[1], "http") == 0) curproxy->mode = PR_MODE_HTTP;
423 else if (strcmp(args[1], "tcp") == 0) curproxy->mode = PR_MODE_TCP;
424 else if (strcmp(args[1], "health") == 0) {
Willy Tarreau77e0dae2020-10-14 15:44:27 +0200425 ha_alert("parsing [%s:%d] : 'mode health' doesn't exist anymore. Please use 'http-request return status 200' instead.\n", file, linenum);
426 err_code |= ERR_ALERT | ERR_FATAL;
427 goto out;
428 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100429 else {
430 ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
431 err_code |= ERR_ALERT | ERR_FATAL;
432 goto out;
433 }
434 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100435 else if (strcmp(args[0], "id") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100436 struct eb32_node *node;
437
438 if (curproxy == &defproxy) {
439 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
440 file, linenum, args[0]);
441 err_code |= ERR_ALERT | ERR_FATAL;
442 goto out;
443 }
444
445 if (alertif_too_many_args(1, file, linenum, args, &err_code))
446 goto out;
447
448 if (!*args[1]) {
449 ha_alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
450 file, linenum, args[0]);
451 err_code |= ERR_ALERT | ERR_FATAL;
452 goto out;
453 }
454
455 curproxy->uuid = atol(args[1]);
456 curproxy->conf.id.key = curproxy->uuid;
457 curproxy->options |= PR_O_FORCED_ID;
458
459 if (curproxy->uuid <= 0) {
460 ha_alert("parsing [%s:%d]: custom id has to be > 0.\n",
461 file, linenum);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465
466 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
467 if (node) {
468 struct proxy *target = container_of(node, struct proxy, conf.id);
469 ha_alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
470 file, linenum, proxy_type_str(curproxy), curproxy->id,
471 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
472 err_code |= ERR_ALERT | ERR_FATAL;
473 goto out;
474 }
475 eb32_insert(&used_proxy_id, &curproxy->conf.id);
476 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100477 else if (strcmp(args[0], "description") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100478 int i, len=0;
479 char *d;
480
481 if (curproxy == &defproxy) {
482 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
483 file, linenum, args[0]);
484 err_code |= ERR_ALERT | ERR_FATAL;
485 goto out;
486 }
487
488 if (!*args[1]) {
489 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
490 file, linenum, args[0]);
491 return -1;
492 }
493
494 for (i = 1; *args[i]; i++)
495 len += strlen(args[i]) + 1;
496
497 d = calloc(1, len);
498 curproxy->desc = d;
499
500 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
501 for (i = 2; *args[i]; i++)
502 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
503
504 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100505 else if (strcmp(args[0], "disabled") == 0) { /* disables this proxy */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100506 if (alertif_too_many_args(0, file, linenum, args, &err_code))
507 goto out;
Willy Tarreauc3914d42020-09-24 08:39:22 +0200508 curproxy->disabled = 1;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100509 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100510 else if (strcmp(args[0], "enabled") == 0) { /* enables this proxy (used to revert a disabled default) */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100511 if (alertif_too_many_args(0, file, linenum, args, &err_code))
512 goto out;
Willy Tarreauc3914d42020-09-24 08:39:22 +0200513 curproxy->disabled = 0;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100514 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100515 else if (strcmp(args[0], "bind-process") == 0) { /* enable this proxy only on some processes */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100516 int cur_arg = 1;
517 unsigned long set = 0;
518
519 while (*args[cur_arg]) {
520 if (strcmp(args[cur_arg], "all") == 0) {
521 set = 0;
522 break;
523 }
Willy Tarreauff9c9142019-02-07 10:39:36 +0100524 if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, &errmsg)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100525 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 cur_arg++;
530 }
531 curproxy->bind_proc = set;
532 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100533 else if (strcmp(args[0], "acl") == 0) { /* add an ACL */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100534 if (curproxy == &defproxy) {
535 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539
540 err = invalid_char(args[1]);
541 if (err) {
542 ha_alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
543 file, linenum, *err, args[1]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546 }
547
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100548 if (strcasecmp(args[1], "or") == 0) {
Tim Duesterhusf1bc24c2020-02-06 22:04:03 +0100549 ha_alert("parsing [%s:%d] : acl name '%s' will never match. 'or' is used to express a "
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100550 "logical disjunction within a condition.\n",
551 file, linenum, args[1]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100556 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
557 ha_alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
558 file, linenum, args[1], errmsg);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100563 else if (strcmp(args[0], "dynamic-cookie-key") == 0) { /* Dynamic cookies secret key */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100564
565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
566 err_code |= ERR_WARN;
567
568 if (*(args[1]) == 0) {
569 ha_alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
570 file, linenum, args[0]);
571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
573 }
574 free(curproxy->dyncookie_key);
575 curproxy->dyncookie_key = strdup(args[1]);
576 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100577 else if (strcmp(args[0], "cookie") == 0) { /* cookie name */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100578 int cur_arg;
579
580 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
581 err_code |= ERR_WARN;
582
583 if (*(args[1]) == 0) {
584 ha_alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
585 file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589
590 curproxy->ck_opts = 0;
591 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
592 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
593 free(curproxy->cookie_name);
594 curproxy->cookie_name = strdup(args[1]);
595 curproxy->cookie_len = strlen(curproxy->cookie_name);
596
597 cur_arg = 2;
598 while (*(args[cur_arg])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100599 if (strcmp(args[cur_arg], "rewrite") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100600 curproxy->ck_opts |= PR_CK_RW;
601 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100602 else if (strcmp(args[cur_arg], "indirect") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100603 curproxy->ck_opts |= PR_CK_IND;
604 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100605 else if (strcmp(args[cur_arg], "insert") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100606 curproxy->ck_opts |= PR_CK_INS;
607 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100608 else if (strcmp(args[cur_arg], "nocache") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100609 curproxy->ck_opts |= PR_CK_NOC;
610 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100611 else if (strcmp(args[cur_arg], "postonly") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100612 curproxy->ck_opts |= PR_CK_POST;
613 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100614 else if (strcmp(args[cur_arg], "preserve") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100615 curproxy->ck_opts |= PR_CK_PSV;
616 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100617 else if (strcmp(args[cur_arg], "prefix") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100618 curproxy->ck_opts |= PR_CK_PFX;
619 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100620 else if (strcmp(args[cur_arg], "httponly") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100621 curproxy->ck_opts |= PR_CK_HTTPONLY;
622 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100623 else if (strcmp(args[cur_arg], "secure") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100624 curproxy->ck_opts |= PR_CK_SECURE;
625 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100626 else if (strcmp(args[cur_arg], "domain") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100627 if (!*args[cur_arg + 1]) {
628 ha_alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
629 file, linenum, args[cur_arg]);
630 err_code |= ERR_ALERT | ERR_FATAL;
631 goto out;
632 }
633
Joao Moraise1583752019-10-30 21:04:00 -0300634 if (!strchr(args[cur_arg + 1], '.')) {
635 /* rfc6265, 5.2.3 The Domain Attribute */
636 ha_warning("parsing [%s:%d]: domain '%s' contains no embedded dot,"
637 " this configuration may not work properly (see RFC6265#5.2.3).\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100638 file, linenum, args[cur_arg + 1]);
639 err_code |= ERR_WARN;
640 }
641
642 err = invalid_domainchar(args[cur_arg + 1]);
643 if (err) {
644 ha_alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
645 file, linenum, *err, args[cur_arg + 1]);
646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
648 }
649
650 if (!curproxy->cookie_domain) {
651 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
652 } else {
653 /* one domain was already specified, add another one by
654 * building the string which will be returned along with
655 * the cookie.
656 */
657 char *new_ptr;
658 int new_len = strlen(curproxy->cookie_domain) +
659 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
660 new_ptr = malloc(new_len);
661 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
662 free(curproxy->cookie_domain);
663 curproxy->cookie_domain = new_ptr;
664 }
665 cur_arg++;
666 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100667 else if (strcmp(args[cur_arg], "maxidle") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100668 unsigned int maxidle;
669 const char *res;
670
671 if (!*args[cur_arg + 1]) {
672 ha_alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
673 file, linenum, args[cur_arg]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677
678 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200679 if (res == PARSE_TIME_OVER) {
680 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
681 file, linenum, args[cur_arg+1], args[cur_arg]);
682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
684 }
685 else if (res == PARSE_TIME_UNDER) {
686 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
687 file, linenum, args[cur_arg+1], args[cur_arg]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100692 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
693 file, linenum, *res, args[cur_arg]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 curproxy->cookie_maxidle = maxidle;
698 cur_arg++;
699 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100700 else if (strcmp(args[cur_arg], "maxlife") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100701 unsigned int maxlife;
702 const char *res;
703
704 if (!*args[cur_arg + 1]) {
705 ha_alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
706 file, linenum, args[cur_arg]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710
Willy Tarreau9faebe32019-06-07 19:00:37 +0200711
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100712 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200713 if (res == PARSE_TIME_OVER) {
714 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
715 file, linenum, args[cur_arg+1], args[cur_arg]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 else if (res == PARSE_TIME_UNDER) {
720 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
721 file, linenum, args[cur_arg+1], args[cur_arg]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100726 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
727 file, linenum, *res, args[cur_arg]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 curproxy->cookie_maxlife = maxlife;
732 cur_arg++;
733 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100734 else if (strcmp(args[cur_arg], "dynamic") == 0) { /* Dynamic persistent cookies secret key */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100735
736 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
737 err_code |= ERR_WARN;
738 curproxy->ck_opts |= PR_CK_DYNAMIC;
739 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100740 else if (strcmp(args[cur_arg], "attr") == 0) {
Christopher Faulet2f533902020-01-21 11:06:48 +0100741 char *val;
742 if (!*args[cur_arg + 1]) {
743 ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
744 file, linenum, args[cur_arg]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748 val = args[cur_arg + 1];
749 while (*val) {
Willy Tarreau90807112020-02-25 08:16:33 +0100750 if (iscntrl((unsigned char)*val) || *val == ';') {
Christopher Faulet2f533902020-01-21 11:06:48 +0100751 ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
752 file, linenum, *val);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 val++;
757 }
758 /* don't add ';' for the first attribute */
759 if (!curproxy->cookie_attrs)
760 curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
761 else
762 memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
763 cur_arg++;
764 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100765
766 else {
Christopher Faulet2f533902020-01-21 11:06:48 +0100767 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 +0100768 file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 cur_arg++;
773 }
774 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
775 ha_alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
776 file, linenum);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 }
779
780 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
781 ha_alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
782 file, linenum);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 }
785
786 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
787 ha_alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
788 file, linenum);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 }
791 }/* end else if (!strcmp(args[0], "cookie")) */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100792 else if (strcmp(args[0], "email-alert") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100793 if (*(args[1]) == 0) {
794 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
795 file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100800 if (strcmp(args[1], "from") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100801 if (*(args[1]) == 0) {
802 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
803 file, linenum, args[1]);
804 err_code |= ERR_ALERT | ERR_FATAL;
805 goto out;
806 }
807 free(curproxy->email_alert.from);
808 curproxy->email_alert.from = strdup(args[2]);
809 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100810 else if (strcmp(args[1], "mailers") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100811 if (*(args[1]) == 0) {
812 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
813 file, linenum, args[1]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 free(curproxy->email_alert.mailers.name);
818 curproxy->email_alert.mailers.name = strdup(args[2]);
819 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100820 else if (strcmp(args[1], "myhostname") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100821 if (*(args[1]) == 0) {
822 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
823 file, linenum, args[1]);
824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
826 }
827 free(curproxy->email_alert.myhostname);
828 curproxy->email_alert.myhostname = strdup(args[2]);
829 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100830 else if (strcmp(args[1], "level") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100831 curproxy->email_alert.level = get_log_level(args[2]);
832 if (curproxy->email_alert.level < 0) {
833 ha_alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
834 file, linenum, args[1], args[2]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100839 else if (strcmp(args[1], "to") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100840 if (*(args[1]) == 0) {
841 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
842 file, linenum, args[1]);
843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
845 }
846 free(curproxy->email_alert.to);
847 curproxy->email_alert.to = strdup(args[2]);
848 }
849 else {
850 ha_alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
851 file, linenum, args[1]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 /* Indicate that the email_alert is at least partially configured */
856 curproxy->email_alert.set = 1;
857 }/* end else if (!strcmp(args[0], "email-alert")) */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100858 else if (strcmp(args[0], "persist") == 0) { /* persist */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100859 if (*(args[1]) == 0) {
860 ha_alert("parsing [%s:%d] : missing persist method.\n",
861 file, linenum);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 if (!strncmp(args[1], "rdp-cookie", 10)) {
867 curproxy->options2 |= PR_O2_RDPC_PRST;
868
869 if (*(args[1] + 10) == '(') { /* cookie name */
870 const char *beg, *end;
871
872 beg = args[1] + 11;
873 end = strchr(beg, ')');
874
875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
877
878 if (!end || end == beg) {
879 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
880 file, linenum);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884
885 free(curproxy->rdp_cookie_name);
886 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
887 curproxy->rdp_cookie_len = end-beg;
888 }
889 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
890 free(curproxy->rdp_cookie_name);
891 curproxy->rdp_cookie_name = strdup("msts");
892 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
893 }
894 else { /* syntax */
895 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
896 file, linenum);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899 }
900 }
901 else {
902 ha_alert("parsing [%s:%d] : unknown persist method.\n",
903 file, linenum);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100908 else if (strcmp(args[0], "appsession") == 0) { /* cookie name */
Tim Duesterhus473c2832019-05-06 01:19:52 +0200909 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 +0100910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100913 else if (strcmp(args[0], "load-server-state-from-file") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
915 err_code |= ERR_WARN;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100916 if (strcmp(args[1], "global") == 0) { /* use the file pointed to by global server-state-file directive */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100917 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
918 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100919 else if (strcmp(args[1], "local") == 0) { /* use the server-state-file-name variable to locate the server-state file */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100920 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
921 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100922 else if (strcmp(args[1], "none") == 0) { /* don't use server-state-file directive for this backend */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100923 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
924 }
925 else {
926 ha_alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
927 file, linenum, args[0], args[1]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100932 else if (strcmp(args[0], "server-state-file-name") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
934 err_code |= ERR_WARN;
Christopher Faulet583b6de2021-02-12 09:27:10 +0100935 if (alertif_too_many_args(1, file, linenum, args, &err_code))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100936 goto out;
Christopher Faulet583b6de2021-02-12 09:27:10 +0100937
938 free(curproxy->server_state_file_name);
939 curproxy->server_state_file_name = NULL;
940
941 if (*(args[1]) == 0 || strcmp(args[1], "use-backend-name") == 0)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100942 curproxy->server_state_file_name = strdup(curproxy->id);
943 else
944 curproxy->server_state_file_name = strdup(args[1]);
945 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100946 else if (strcmp(args[0], "max-session-srv-conns") == 0) {
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +0100947 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
948 err_code |= ERR_WARN;
949 if (*(args[1]) == 0) {
950 ha_alert("parsine [%s:%d] : '%s' expects a number. Got no argument\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955 curproxy->max_out_conns = atoi(args[1]);
956 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100957 else if (strcmp(args[0], "capture") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100958 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
959 err_code |= ERR_WARN;
960
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100961 if (strcmp(args[1], "cookie") == 0) { /* name of a cookie to capture */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100962 if (curproxy == &defproxy) {
963 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967
968 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
969 goto out;
970
971 if (*(args[4]) == 0) {
972 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
973 file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 free(curproxy->capture_name);
978 curproxy->capture_name = strdup(args[2]);
979 curproxy->capture_namelen = strlen(curproxy->capture_name);
980 curproxy->capture_len = atol(args[4]);
981 curproxy->to_log |= LW_COOKIE;
982 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100983 else if (strcmp(args[1], "request") == 0 && strcmp(args[2], "header") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100984 struct cap_hdr *hdr;
985
986 if (curproxy == &defproxy) {
987 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991
992 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
993 goto out;
994
995 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
996 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
997 file, linenum, args[0], args[1]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001
1002 hdr = calloc(1, sizeof(*hdr));
1003 hdr->next = curproxy->req_cap;
1004 hdr->name = strdup(args[3]);
1005 hdr->namelen = strlen(args[3]);
1006 hdr->len = atol(args[5]);
1007 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1008 hdr->index = curproxy->nb_req_cap++;
1009 curproxy->req_cap = hdr;
1010 curproxy->to_log |= LW_REQHDR;
1011 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001012 else if (strcmp(args[1], "response") == 0 && strcmp(args[2], "header") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001013 struct cap_hdr *hdr;
1014
1015 if (curproxy == &defproxy) {
1016 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019 }
1020
1021 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1022 goto out;
1023
1024 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1025 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1026 file, linenum, args[0], args[1]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 hdr = calloc(1, sizeof(*hdr));
1031 hdr->next = curproxy->rsp_cap;
1032 hdr->name = strdup(args[3]);
1033 hdr->namelen = strlen(args[3]);
1034 hdr->len = atol(args[5]);
1035 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1036 hdr->index = curproxy->nb_rsp_cap++;
1037 curproxy->rsp_cap = hdr;
1038 curproxy->to_log |= LW_RSPHDR;
1039 }
1040 else {
1041 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001047 else if (strcmp(args[0], "retries") == 0) { /* connection retries */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001048 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1049 err_code |= ERR_WARN;
1050
1051 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1052 goto out;
1053
1054 if (*(args[1]) == 0) {
1055 ha_alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1056 file, linenum, args[0]);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
1060 curproxy->conn_retries = atol(args[1]);
1061 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001062 else if (strcmp(args[0], "http-request") == 0) { /* request access control: allow/deny/auth */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001063 struct act_rule *rule;
1064
1065 if (curproxy == &defproxy) {
1066 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1067 err_code |= ERR_ALERT | ERR_FATAL;
1068 goto out;
1069 }
1070
1071 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
1072 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001073 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001074 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1075 file, linenum, args[0]);
1076 err_code |= ERR_WARN;
1077 }
1078
1079 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
1080
1081 if (!rule) {
1082 err_code |= ERR_ALERT | ERR_ABORT;
1083 goto out;
1084 }
1085
1086 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
1087 err_code |= warnif_cond_conflicts(rule->cond,
1088 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1089 file, linenum);
1090
1091 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
1092 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001093 else if (strcmp(args[0], "http-response") == 0) { /* response access control */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001094 struct act_rule *rule;
1095
1096 if (curproxy == &defproxy) {
1097 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
1100 }
1101
1102 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
1103 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001104 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001105 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1106 file, linenum, args[0]);
1107 err_code |= ERR_WARN;
1108 }
1109
1110 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
1111
1112 if (!rule) {
1113 err_code |= ERR_ALERT | ERR_ABORT;
1114 goto out;
1115 }
1116
1117 err_code |= warnif_cond_conflicts(rule->cond,
1118 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1119 file, linenum);
1120
1121 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
1122 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001123 else if (strcmp(args[0], "http-after-response") == 0) {
Christopher Faulet6d0c3df2020-01-22 09:26:35 +01001124 struct act_rule *rule;
1125
1126 if (curproxy == &defproxy) {
1127 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
1130 }
1131
1132 if (!LIST_ISEMPTY(&curproxy->http_after_res_rules) &&
1133 !LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->cond &&
1134 (LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
1135 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1136 file, linenum, args[0]);
1137 err_code |= ERR_WARN;
1138 }
1139
1140 rule = parse_http_after_res_cond((const char **)args + 1, file, linenum, curproxy);
1141
1142 if (!rule) {
1143 err_code |= ERR_ALERT | ERR_ABORT;
1144 goto out;
1145 }
1146
1147 err_code |= warnif_cond_conflicts(rule->cond,
1148 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1149 file, linenum);
1150
1151 LIST_ADDQ(&curproxy->http_after_res_rules, &rule->list);
1152 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001153 else if (strcmp(args[0], "http-send-name-header") == 0) { /* send server name in request header */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001154 /* set the header name and length into the proxy structure */
1155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1156 err_code |= ERR_WARN;
1157
1158 if (!*args[1]) {
1159 ha_alert("parsing [%s:%d] : '%s' requires a header string.\n",
1160 file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
1164
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001165 /* set the desired header name, in lower case */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001166 free(curproxy->server_id_hdr_name);
1167 curproxy->server_id_hdr_name = strdup(args[1]);
1168 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001169 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 +01001170 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001171 else if (strcmp(args[0], "block") == 0) {
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001172 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 +01001173
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001176 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001177 else if (strcmp(args[0], "redirect") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001178 struct redirect_rule *rule;
1179
1180 if (curproxy == &defproxy) {
1181 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185
1186 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
1187 ha_alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
1188 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191 }
1192
1193 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1194 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
1195 err_code |= warnif_cond_conflicts(rule->cond,
1196 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1197 file, linenum);
1198 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001199 else if (strcmp(args[0], "use_backend") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001200 struct switching_rule *rule;
1201
1202 if (curproxy == &defproxy) {
1203 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207
1208 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1209 err_code |= ERR_WARN;
1210
1211 if (*(args[1]) == 0) {
1212 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
1218 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1219 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1220 file, linenum, errmsg);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
1225 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
1226 }
1227 else if (*args[2]) {
1228 ha_alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
1229 file, linenum, args[2]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
1232 }
1233
1234 rule = calloc(1, sizeof(*rule));
1235 if (!rule) {
1236 ha_alert("Out of memory error.\n");
1237 goto out;
1238 }
1239 rule->cond = cond;
1240 rule->be.name = strdup(args[1]);
Tim Duesterhus5ce5a152021-01-03 22:54:43 +01001241 if (!rule->be.name) {
1242 ha_alert("Out of memory error.\n");
1243 goto out;
1244 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001245 rule->line = linenum;
1246 rule->file = strdup(file);
1247 if (!rule->file) {
1248 ha_alert("Out of memory error.\n");
1249 goto out;
1250 }
1251 LIST_INIT(&rule->list);
1252 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1253 }
1254 else if (strcmp(args[0], "use-server") == 0) {
1255 struct server_rule *rule;
1256
1257 if (curproxy == &defproxy) {
1258 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1264 err_code |= ERR_WARN;
1265
1266 if (*(args[1]) == 0) {
1267 ha_alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1273 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1274 file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278
1279 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1280 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1281 file, linenum, errmsg);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285
1286 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1287
1288 rule = calloc(1, sizeof(*rule));
1289 rule->cond = cond;
1290 rule->srv.name = strdup(args[1]);
Jerome Magnin824186b2020-03-29 09:37:12 +02001291 rule->line = linenum;
1292 rule->file = strdup(file);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001293 LIST_INIT(&rule->list);
1294 LIST_ADDQ(&curproxy->server_rules, &rule->list);
1295 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
1296 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001297 else if ((strcmp(args[0], "force-persist") == 0) ||
1298 (strcmp(args[0], "ignore-persist") == 0)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001299 struct persist_rule *rule;
1300
1301 if (curproxy == &defproxy) {
1302 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1308 err_code |= ERR_WARN;
1309
1310 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
1311 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1312 file, linenum, args[0]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316
1317 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
1318 ha_alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
1319 file, linenum, args[0], errmsg);
1320 err_code |= ERR_ALERT | ERR_FATAL;
1321 goto out;
1322 }
1323
1324 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
1325 * where force-persist is applied.
1326 */
1327 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
1328
1329 rule = calloc(1, sizeof(*rule));
1330 rule->cond = cond;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001331 if (strcmp(args[0], "force-persist") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001332 rule->type = PERSIST_TYPE_FORCE;
1333 } else {
1334 rule->type = PERSIST_TYPE_IGNORE;
1335 }
1336 LIST_INIT(&rule->list);
1337 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
1338 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001339 else if (strcmp(args[0], "stick-table") == 0) {
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001340 struct stktable *other;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001341
1342 if (curproxy == &defproxy) {
1343 ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
1344 file, linenum);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001349 other = stktable_find_by_name(curproxy->id);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001350 if (other) {
1351 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 +01001352 file, linenum, curproxy->id,
1353 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
1354 other->proxy ? other->id : other->peers.p->id,
1355 other->conf.file, other->conf.line);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
1358 }
1359
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001360 curproxy->table = calloc(1, sizeof *curproxy->table);
1361 if (!curproxy->table) {
1362 ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
1363 file, linenum, args[0], args[1]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367
Frédéric Lécaillec02766a2019-03-20 15:06:55 +01001368 err_code |= parse_stick_table(file, linenum, args, curproxy->table,
1369 curproxy->id, curproxy->id, NULL);
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001370 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001371 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001372
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001373 /* Store the proxy in the stick-table. */
1374 curproxy->table->proxy = curproxy;
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001375
1376 stktable_store_name(curproxy->table);
1377 curproxy->table->next = stktables_list;
1378 stktables_list = curproxy->table;
Frédéric Lécaille015e4d72019-03-19 14:55:01 +01001379
1380 /* Add this proxy to the list of proxies which refer to its stick-table. */
1381 if (curproxy->table->proxies_list != curproxy) {
1382 curproxy->next_stkt_ref = curproxy->table->proxies_list;
1383 curproxy->table->proxies_list = curproxy;
1384 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001385 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001386 else if (strcmp(args[0], "stick") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001387 struct sticking_rule *rule;
1388 struct sample_expr *expr;
1389 int myidx = 0;
1390 const char *name = NULL;
1391 int flags;
1392
1393 if (curproxy == &defproxy) {
1394 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
1398
1399 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
1400 err_code |= ERR_WARN;
1401 goto out;
1402 }
1403
1404 myidx++;
1405 if ((strcmp(args[myidx], "store") == 0) ||
1406 (strcmp(args[myidx], "store-request") == 0)) {
1407 myidx++;
1408 flags = STK_IS_STORE;
1409 }
1410 else if (strcmp(args[myidx], "store-response") == 0) {
1411 myidx++;
1412 flags = STK_IS_STORE | STK_ON_RSP;
1413 }
1414 else if (strcmp(args[myidx], "match") == 0) {
1415 myidx++;
1416 flags = STK_IS_MATCH;
1417 }
1418 else if (strcmp(args[myidx], "on") == 0) {
1419 myidx++;
1420 flags = STK_IS_MATCH | STK_IS_STORE;
1421 }
1422 else {
1423 ha_alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
1424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
1426 }
1427
1428 if (*(args[myidx]) == 0) {
1429 ha_alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433
1434 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreaue3b57bf2020-02-14 16:50:14 +01001435 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001436 if (!expr) {
1437 ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
1438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
1440 }
1441
1442 if (flags & STK_ON_RSP) {
1443 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
1444 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
1445 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 free(expr);
1448 goto out;
1449 }
1450 } else {
1451 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
1452 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
1453 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 free(expr);
1456 goto out;
1457 }
1458 }
1459
Christopher Faulet711ed6a2019-07-16 14:16:10 +02001460 /* check if we need to allocate an http_txn struct for HTTP parsing */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001461 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
1462
1463 if (strcmp(args[myidx], "table") == 0) {
1464 myidx++;
1465 name = args[myidx++];
1466 }
1467
1468 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
1469 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
1470 ha_alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
1471 file, linenum, args[0], errmsg);
1472 err_code |= ERR_ALERT | ERR_FATAL;
1473 free(expr);
1474 goto out;
1475 }
1476 }
1477 else if (*(args[myidx])) {
1478 ha_alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
1479 file, linenum, args[0], args[myidx]);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 free(expr);
1482 goto out;
1483 }
1484 if (flags & STK_ON_RSP)
1485 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
1486 else
1487 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1488
1489 rule = calloc(1, sizeof(*rule));
1490 rule->cond = cond;
1491 rule->expr = expr;
1492 rule->flags = flags;
1493 rule->table.name = name ? strdup(name) : NULL;
1494 LIST_INIT(&rule->list);
1495 if (flags & STK_ON_RSP)
1496 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
1497 else
1498 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
1499 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001500 else if (strcmp(args[0], "stats") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001501 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1502 curproxy->uri_auth = NULL; /* we must detach from the default config */
1503
1504 if (!*args[1]) {
1505 goto stats_error_parsing;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001506 } else if (strcmp(args[1], "admin") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001507 struct stats_admin_rule *rule;
1508
1509 if (curproxy == &defproxy) {
1510 ha_alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1516 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1517 err_code |= ERR_ALERT | ERR_ABORT;
1518 goto out;
1519 }
1520
1521 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1522 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1523 file, linenum, args[0], args[1]);
1524 err_code |= ERR_ALERT | ERR_FATAL;
1525 goto out;
1526 }
1527 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1528 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
1529 file, linenum, args[0], args[1], errmsg);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
1534 err_code |= warnif_cond_conflicts(cond,
1535 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1536 file, linenum);
1537
1538 rule = calloc(1, sizeof(*rule));
1539 rule->cond = cond;
1540 LIST_INIT(&rule->list);
1541 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001542 } else if (strcmp(args[1], "uri") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001543 if (*(args[2]) == 0) {
1544 ha_alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1548 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1549 err_code |= ERR_ALERT | ERR_ABORT;
1550 goto out;
1551 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001552 } else if (strcmp(args[1], "realm") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001553 if (*(args[2]) == 0) {
1554 ha_alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1558 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1559 err_code |= ERR_ALERT | ERR_ABORT;
1560 goto out;
1561 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001562 } else if (strcmp(args[1], "refresh") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001563 unsigned interval;
1564
1565 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02001566 if (err == PARSE_TIME_OVER) {
1567 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to stats refresh interval, maximum value is 2147483647 s (~68 years).\n",
1568 file, linenum, args[2]);
1569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
1571 }
1572 else if (err == PARSE_TIME_UNDER) {
1573 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to stats refresh interval, minimum non-null value is 1 s.\n",
1574 file, linenum, args[2]);
1575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
1577 }
1578 else if (err) {
1579 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to stats refresh interval.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001580 file, linenum, *err);
1581 err_code |= ERR_ALERT | ERR_FATAL;
1582 goto out;
1583 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1584 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1585 err_code |= ERR_ALERT | ERR_ABORT;
1586 goto out;
1587 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001588 } else if (strcmp(args[1], "http-request") == 0) { /* request access control: allow/deny/auth */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001589 struct act_rule *rule;
1590
1591 if (curproxy == &defproxy) {
1592 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
1595 }
1596
1597 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1598 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1599 err_code |= ERR_ALERT | ERR_ABORT;
1600 goto out;
1601 }
1602
1603 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
1604 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
1605 ha_warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1606 file, linenum, args[0]);
1607 err_code |= ERR_WARN;
1608 }
1609
1610 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
1611
1612 if (!rule) {
1613 err_code |= ERR_ALERT | ERR_ABORT;
1614 goto out;
1615 }
1616
1617 err_code |= warnif_cond_conflicts(rule->cond,
1618 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1619 file, linenum);
1620 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
1621
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001622 } else if (strcmp(args[1], "auth") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001623 if (*(args[2]) == 0) {
1624 ha_alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
1627 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1628 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1629 err_code |= ERR_ALERT | ERR_ABORT;
1630 goto out;
1631 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001632 } else if (strcmp(args[1], "scope") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001633 if (*(args[2]) == 0) {
1634 ha_alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1638 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1639 err_code |= ERR_ALERT | ERR_ABORT;
1640 goto out;
1641 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001642 } else if (strcmp(args[1], "enable") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001643 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1644 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1645 err_code |= ERR_ALERT | ERR_ABORT;
1646 goto out;
1647 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001648 } else if (strcmp(args[1], "hide-version") == 0) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001649 if (!stats_set_flag(&curproxy->uri_auth, STAT_HIDEVER)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001650 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1651 err_code |= ERR_ALERT | ERR_ABORT;
1652 goto out;
1653 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001654 } else if (strcmp(args[1], "show-legends") == 0) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001655 if (!stats_set_flag(&curproxy->uri_auth, STAT_SHLGNDS)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001656 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1657 err_code |= ERR_ALERT | ERR_ABORT;
1658 goto out;
1659 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001660 } else if (strcmp(args[1], "show-modules") == 0) {
Amaury Denoyelle0b70a8a2020-10-05 11:49:45 +02001661 if (!stats_set_flag(&curproxy->uri_auth, STAT_SHMODULES)) {
1662 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1663 err_code |= ERR_ALERT | ERR_ABORT;
1664 goto out;
1665 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001666 } else if (strcmp(args[1], "show-node") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001667
1668 if (*args[2]) {
1669 int i;
1670 char c;
1671
1672 for (i=0; args[2][i]; i++) {
1673 c = args[2][i];
1674 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1675 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
1676 break;
1677 }
1678
1679 if (!i || args[2][i]) {
1680 ha_alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1681 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1682 file, linenum, args[0], args[1]);
1683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
1686 }
1687
1688 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1689 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1690 err_code |= ERR_ALERT | ERR_ABORT;
1691 goto out;
1692 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001693 } else if (strcmp(args[1], "show-desc") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001694 char *desc = NULL;
1695
1696 if (*args[2]) {
1697 int i, len=0;
1698 char *d;
1699
1700 for (i = 2; *args[i]; i++)
1701 len += strlen(args[i]) + 1;
1702
1703 desc = d = calloc(1, len);
1704
1705 d += snprintf(d, desc + len - d, "%s", args[2]);
1706 for (i = 3; *args[i]; i++)
1707 d += snprintf(d, desc + len - d, " %s", args[i]);
1708 }
1709
1710 if (!*args[2] && !global.desc)
1711 ha_warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1712 file, linenum, args[1]);
1713 else {
1714 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
1715 free(desc);
1716 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1717 err_code |= ERR_ALERT | ERR_ABORT;
1718 goto out;
1719 }
1720 free(desc);
1721 }
1722 } else {
1723stats_error_parsing:
1724 ha_alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
1725 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001730 else if (strcmp(args[0], "option") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001731 int optnum;
1732
1733 if (*(args[1]) == '\0') {
1734 ha_alert("parsing [%s:%d]: '%s' expects an option name.\n",
1735 file, linenum, args[0]);
1736 err_code |= ERR_ALERT | ERR_FATAL;
1737 goto out;
1738 }
1739
1740 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001741 if (strcmp(args[1], cfg_opts[optnum].name) == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001742 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
1743 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
1744 file, linenum, cfg_opts[optnum].name);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1749 goto out;
1750
1751 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1752 err_code |= ERR_WARN;
1753 goto out;
1754 }
1755
1756 curproxy->no_options &= ~cfg_opts[optnum].val;
1757 curproxy->options &= ~cfg_opts[optnum].val;
1758
1759 switch (kwm) {
1760 case KWM_STD:
1761 curproxy->options |= cfg_opts[optnum].val;
1762 break;
1763 case KWM_NO:
1764 curproxy->no_options |= cfg_opts[optnum].val;
1765 break;
1766 case KWM_DEF: /* already cleared */
1767 break;
1768 }
1769
1770 goto out;
1771 }
1772 }
1773
1774 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001775 if (strcmp(args[1], cfg_opts2[optnum].name) == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001776 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
1777 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
1778 file, linenum, cfg_opts2[optnum].name);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1783 goto out;
1784 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1785 err_code |= ERR_WARN;
1786 goto out;
1787 }
1788
Christopher Faulet31930372019-07-15 10:16:58 +02001789 /* "[no] option http-use-htx" is deprecated */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001790 if (strcmp(cfg_opts2[optnum].name, "http-use-htx") == 0) {
Christopher Fauletf89f0992019-07-19 11:17:38 +02001791 if (kwm ==KWM_NO) {
1792 ha_warning("parsing [%s:%d]: option '%s' is deprecated and ignored."
1793 " The HTX mode is now the only supported mode.\n",
1794 file, linenum, cfg_opts2[optnum].name);
1795 err_code |= ERR_WARN;
1796 }
Christopher Faulet31930372019-07-15 10:16:58 +02001797 goto out;
1798 }
1799
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001800 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1801 curproxy->options2 &= ~cfg_opts2[optnum].val;
1802
1803 switch (kwm) {
1804 case KWM_STD:
1805 curproxy->options2 |= cfg_opts2[optnum].val;
1806 break;
1807 case KWM_NO:
1808 curproxy->no_options2 |= cfg_opts2[optnum].val;
1809 break;
1810 case KWM_DEF: /* already cleared */
1811 break;
1812 }
1813 goto out;
1814 }
1815 }
1816
1817 /* HTTP options override each other. They can be cancelled using
1818 * "no option xxx" which only switches to default mode if the mode
1819 * was this one (useful for cancelling options set in defaults
1820 * sections).
1821 */
1822 if (strcmp(args[1], "httpclose") == 0 || strcmp(args[1], "forceclose") == 0) {
Tim Duesterhus10c6c162019-05-14 20:58:00 +02001823 if (strcmp(args[1], "forceclose") == 0) {
1824 if (!already_warned(WARN_FORCECLOSE_DEPRECATED))
1825 ha_warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'httpclose', and will not be supported by future versions.\n",
1826 file, linenum, args[1]);
1827 err_code |= ERR_WARN;
1828 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001829 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1830 goto out;
1831 if (kwm == KWM_STD) {
1832 curproxy->options &= ~PR_O_HTTP_MODE;
1833 curproxy->options |= PR_O_HTTP_CLO;
1834 goto out;
1835 }
1836 else if (kwm == KWM_NO) {
1837 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO)
1838 curproxy->options &= ~PR_O_HTTP_MODE;
1839 goto out;
1840 }
1841 }
1842 else if (strcmp(args[1], "http-server-close") == 0) {
1843 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1844 goto out;
1845 if (kwm == KWM_STD) {
1846 curproxy->options &= ~PR_O_HTTP_MODE;
1847 curproxy->options |= PR_O_HTTP_SCL;
1848 goto out;
1849 }
1850 else if (kwm == KWM_NO) {
1851 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
1852 curproxy->options &= ~PR_O_HTTP_MODE;
1853 goto out;
1854 }
1855 }
1856 else if (strcmp(args[1], "http-keep-alive") == 0) {
1857 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1858 goto out;
1859 if (kwm == KWM_STD) {
1860 curproxy->options &= ~PR_O_HTTP_MODE;
1861 curproxy->options |= PR_O_HTTP_KAL;
1862 goto out;
1863 }
1864 else if (kwm == KWM_NO) {
1865 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
1866 curproxy->options &= ~PR_O_HTTP_MODE;
1867 goto out;
1868 }
1869 }
1870 else if (strcmp(args[1], "http-tunnel") == 0) {
Christopher Faulet73e8ede2019-07-16 15:04:46 +02001871 ha_warning("parsing [%s:%d]: the option '%s' is deprecated and will be removed in next version.\n",
1872 file, linenum, args[1]);
1873 err_code |= ERR_WARN;
1874 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001875 }
1876
1877 /* Redispatch can take an integer argument that control when the
1878 * resispatch occurs. All values are relative to the retries option.
1879 * This can be cancelled using "no option xxx".
1880 */
1881 if (strcmp(args[1], "redispatch") == 0) {
1882 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
1883 err_code |= ERR_WARN;
1884 goto out;
1885 }
1886
1887 curproxy->no_options &= ~PR_O_REDISP;
1888 curproxy->options &= ~PR_O_REDISP;
1889
1890 switch (kwm) {
1891 case KWM_STD:
1892 curproxy->options |= PR_O_REDISP;
1893 curproxy->redispatch_after = -1;
1894 if(*args[2]) {
1895 curproxy->redispatch_after = atol(args[2]);
1896 }
1897 break;
1898 case KWM_NO:
1899 curproxy->no_options |= PR_O_REDISP;
1900 curproxy->redispatch_after = 0;
1901 break;
1902 case KWM_DEF: /* already cleared */
1903 break;
1904 }
1905 goto out;
1906 }
1907
1908 if (kwm != KWM_STD) {
1909 ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
1910 file, linenum, args[1]);
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001915 if (strcmp(args[1], "httplog") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001916 char *logformat;
1917 /* generate a complete HTTP log */
1918 logformat = default_http_log_format;
1919 if (*(args[2]) != '\0') {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001920 if (strcmp(args[2], "clf") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001921 curproxy->options2 |= PR_O2_CLFLOG;
1922 logformat = clf_http_log_format;
1923 } else {
1924 ha_alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
1925 err_code |= ERR_ALERT | ERR_FATAL;
1926 goto out;
1927 }
1928 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
1929 goto out;
1930 }
1931 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
1932 char *oldlogformat = "log-format";
1933 char *clflogformat = "";
1934
1935 if (curproxy->conf.logformat_string == default_http_log_format)
1936 oldlogformat = "option httplog";
1937 else if (curproxy->conf.logformat_string == default_tcp_log_format)
1938 oldlogformat = "option tcplog";
1939 else if (curproxy->conf.logformat_string == clf_http_log_format)
1940 oldlogformat = "option httplog clf";
1941 if (logformat == clf_http_log_format)
1942 clflogformat = " clf";
1943 ha_warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
1944 file, linenum, clflogformat, oldlogformat);
1945 }
1946 if (curproxy->conf.logformat_string != default_http_log_format &&
1947 curproxy->conf.logformat_string != default_tcp_log_format &&
1948 curproxy->conf.logformat_string != clf_http_log_format)
1949 free(curproxy->conf.logformat_string);
1950 curproxy->conf.logformat_string = logformat;
1951
1952 free(curproxy->conf.lfs_file);
1953 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
1954 curproxy->conf.lfs_line = curproxy->conf.args.line;
1955
1956 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
1957 ha_warning("parsing [%s:%d] : backend '%s' : 'option httplog' directive is ignored in backends.\n",
1958 file, linenum, curproxy->id);
1959 err_code |= ERR_WARN;
1960 }
1961 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001962 else if (strcmp(args[1], "tcplog") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001963 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
1964 char *oldlogformat = "log-format";
1965
1966 if (curproxy->conf.logformat_string == default_http_log_format)
1967 oldlogformat = "option httplog";
1968 else if (curproxy->conf.logformat_string == default_tcp_log_format)
1969 oldlogformat = "option tcplog";
1970 else if (curproxy->conf.logformat_string == clf_http_log_format)
1971 oldlogformat = "option httplog clf";
1972 ha_warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
1973 file, linenum, oldlogformat);
1974 }
1975 /* generate a detailed TCP log */
1976 if (curproxy->conf.logformat_string != default_http_log_format &&
1977 curproxy->conf.logformat_string != default_tcp_log_format &&
1978 curproxy->conf.logformat_string != clf_http_log_format)
1979 free(curproxy->conf.logformat_string);
1980 curproxy->conf.logformat_string = default_tcp_log_format;
1981
1982 free(curproxy->conf.lfs_file);
1983 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
1984 curproxy->conf.lfs_line = curproxy->conf.args.line;
1985
1986 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
1987 goto out;
1988
1989 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
1990 ha_warning("parsing [%s:%d] : backend '%s' : 'option tcplog' directive is ignored in backends.\n",
1991 file, linenum, curproxy->id);
1992 err_code |= ERR_WARN;
1993 }
1994 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001995 else if (strcmp(args[1], "tcpka") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001996 /* enable TCP keep-alives on client and server streams */
1997 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1998 err_code |= ERR_WARN;
1999
2000 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2001 goto out;
2002
2003 if (curproxy->cap & PR_CAP_FE)
2004 curproxy->options |= PR_O_TCP_CLI_KA;
2005 if (curproxy->cap & PR_CAP_BE)
2006 curproxy->options |= PR_O_TCP_SRV_KA;
2007 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002008 else if (strcmp(args[1], "httpchk") == 0) {
Christopher Faulet6c2a7432020-04-09 14:48:48 +02002009 err_code |= proxy_parse_httpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2010 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002011 goto out;
2012 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002013 else if (strcmp(args[1], "ssl-hello-chk") == 0) {
Christopher Faulet811f78c2020-04-01 11:10:27 +02002014 err_code |= proxy_parse_ssl_hello_chk_opt(args, 0, curproxy, &defproxy, file, linenum);
2015 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002016 goto out;
2017 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002018 else if (strcmp(args[1], "smtpchk") == 0) {
Christopher Fauletfbcc77c2020-04-01 20:54:05 +02002019 err_code |= proxy_parse_smtpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2020 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002021 goto out;
2022 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002023 else if (strcmp(args[1], "pgsql-check") == 0) {
Christopher Fauletce355072020-04-02 11:44:39 +02002024 err_code |= proxy_parse_pgsql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2025 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002026 goto out;
2027 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002028 else if (strcmp(args[1], "redis-check") == 0) {
Christopher Faulet33f05df2020-04-01 11:08:50 +02002029 err_code |= proxy_parse_redis_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2030 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002031 goto out;
2032 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002033 else if (strcmp(args[1], "mysql-check") == 0) {
Christopher Fauletf2b3be52020-04-02 18:07:37 +02002034 err_code |= proxy_parse_mysql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2035 if (err_code & ERR_FATAL)
2036 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002037 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002038 else if (strcmp(args[1], "ldap-check") == 0) {
Christopher Faulet1997eca2020-04-03 23:13:50 +02002039 err_code |= proxy_parse_ldap_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2040 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002041 goto out;
2042 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002043 else if (strcmp(args[1], "spop-check") == 0) {
Christopher Faulet267b01b2020-04-04 10:27:09 +02002044 err_code |= proxy_parse_spop_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2045 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002046 goto out;
2047 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002048 else if (strcmp(args[1], "tcp-check") == 0) {
Christopher Faulet430e4802020-04-09 15:28:16 +02002049 err_code |= proxy_parse_tcp_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2050 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002051 goto out;
2052 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002053 else if (strcmp(args[1], "external-check") == 0) {
Christopher Faulet6f557912020-04-09 15:58:50 +02002054 err_code |= proxy_parse_external_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2055 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002056 goto out;
2057 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002058 else if (strcmp(args[1], "forwardfor") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002059 int cur_arg;
2060
2061 /* insert x-forwarded-for field, but not for the IP address listed as an except.
Christopher Faulet31930372019-07-15 10:16:58 +02002062 * set default options (ie: bitfield, header name, etc)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002063 */
2064
2065 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
2066
2067 free(curproxy->fwdfor_hdr_name);
2068 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2069 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2070
2071 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2072 cur_arg = 2;
2073 while (*(args[cur_arg])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002074 if (strcmp(args[cur_arg], "except") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002075 /* suboption except - needs additional argument for it */
2076 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
2077 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2078 file, linenum, args[0], args[1], args[cur_arg]);
2079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
2081 }
2082 /* flush useless bits */
2083 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
2084 cur_arg += 2;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002085 } else if (strcmp(args[cur_arg], "header") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002086 /* suboption header - needs additional argument for it */
2087 if (*(args[cur_arg+1]) == 0) {
2088 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2089 file, linenum, args[0], args[1], args[cur_arg]);
2090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
2093 free(curproxy->fwdfor_hdr_name);
2094 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2095 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2096 cur_arg += 2;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002097 } else if (strcmp(args[cur_arg], "if-none") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002098 curproxy->options &= ~PR_O_FF_ALWAYS;
2099 cur_arg += 1;
2100 } else {
2101 /* unknown suboption - catchall */
2102 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
2103 file, linenum, args[0], args[1]);
2104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
2107 } /* end while loop */
2108 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002109 else if (strcmp(args[1], "originalto") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002110 int cur_arg;
2111
2112 /* insert x-original-to field, but not for the IP address listed as an except.
2113 * set default options (ie: bitfield, header name, etc)
2114 */
2115
2116 curproxy->options |= PR_O_ORGTO;
2117
2118 free(curproxy->orgto_hdr_name);
2119 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2120 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2121
2122 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
2123 cur_arg = 2;
2124 while (*(args[cur_arg])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002125 if (strcmp(args[cur_arg], "except") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002126 /* suboption except - needs additional argument for it */
2127 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
2128 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2129 file, linenum, args[0], args[1], args[cur_arg]);
2130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
2132 }
2133 /* flush useless bits */
2134 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2135 cur_arg += 2;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002136 } else if (strcmp(args[cur_arg], "header") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002137 /* suboption header - needs additional argument for it */
2138 if (*(args[cur_arg+1]) == 0) {
2139 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2140 file, linenum, args[0], args[1], args[cur_arg]);
2141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
2143 }
2144 free(curproxy->orgto_hdr_name);
2145 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2146 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2147 cur_arg += 2;
2148 } else {
2149 /* unknown suboption - catchall */
2150 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2151 file, linenum, args[0], args[1]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155 } /* end while loop */
2156 }
2157 else {
2158 ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
2159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
2161 }
2162 goto out;
2163 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002164 else if (strcmp(args[0], "default_backend") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002165 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2166 err_code |= ERR_WARN;
2167
2168 if (*(args[1]) == 0) {
2169 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
2170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
2172 }
2173 free(curproxy->defbe.name);
2174 curproxy->defbe.name = strdup(args[1]);
2175
2176 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
2177 goto out;
2178 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002179 else if (strcmp(args[0], "redispatch") == 0 || strcmp(args[0], "redisp") == 0) {
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002180 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 +01002181
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002184 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002185 else if (strcmp(args[0], "http-reuse") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002186 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2187 err_code |= ERR_WARN;
2188
2189 if (strcmp(args[1], "never") == 0) {
2190 /* enable a graceful server shutdown on an HTTP 404 response */
2191 curproxy->options &= ~PR_O_REUSE_MASK;
2192 curproxy->options |= PR_O_REUSE_NEVR;
2193 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2194 goto out;
2195 }
2196 else if (strcmp(args[1], "safe") == 0) {
2197 /* enable a graceful server shutdown on an HTTP 404 response */
2198 curproxy->options &= ~PR_O_REUSE_MASK;
2199 curproxy->options |= PR_O_REUSE_SAFE;
2200 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2201 goto out;
2202 }
2203 else if (strcmp(args[1], "aggressive") == 0) {
2204 curproxy->options &= ~PR_O_REUSE_MASK;
2205 curproxy->options |= PR_O_REUSE_AGGR;
2206 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2207 goto out;
2208 }
2209 else if (strcmp(args[1], "always") == 0) {
2210 /* enable a graceful server shutdown on an HTTP 404 response */
2211 curproxy->options &= ~PR_O_REUSE_MASK;
2212 curproxy->options |= PR_O_REUSE_ALWS;
2213 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2214 goto out;
2215 }
2216 else {
2217 ha_alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
2221 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002222 else if (strcmp(args[0], "monitor") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002223 if (curproxy == &defproxy) {
2224 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
2227 }
2228
2229 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2230 err_code |= ERR_WARN;
2231
2232 if (strcmp(args[1], "fail") == 0) {
2233 /* add a condition to fail monitor requests */
2234 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2235 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2236 file, linenum, args[0], args[1]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240
2241 err_code |= warnif_misplaced_monitor(curproxy, file, linenum, "monitor fail");
2242 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2243 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
2244 file, linenum, args[0], args[1], errmsg);
2245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
2247 }
2248 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2249 }
2250 else {
2251 ha_alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255 }
Willy Tarreaue5733232019-05-22 19:24:06 +02002256#ifdef USE_TPROXY
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002257 else if (strcmp(args[0], "transparent") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002258 /* enable transparent proxy connections */
2259 curproxy->options |= PR_O_TRANSP;
2260 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2261 goto out;
2262 }
2263#endif
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002264 else if (strcmp(args[0], "maxconn") == 0) { /* maxconn */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002265 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
2266 err_code |= ERR_WARN;
2267
2268 if (*(args[1]) == 0) {
2269 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273 curproxy->maxconn = atol(args[1]);
2274 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2275 goto out;
2276 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002277 else if (strcmp(args[0], "backlog") == 0) { /* backlog */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002278 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2279 err_code |= ERR_WARN;
2280
2281 if (*(args[1]) == 0) {
2282 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
2285 }
2286 curproxy->backlog = atol(args[1]);
2287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2288 goto out;
2289 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002290 else if (strcmp(args[0], "fullconn") == 0) { /* fullconn */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002291 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
2292 err_code |= ERR_WARN;
2293
2294 if (*(args[1]) == 0) {
2295 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
2298 }
2299 curproxy->fullconn = atol(args[1]);
2300 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2301 goto out;
2302 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002303 else if (strcmp(args[0], "grace") == 0) { /* grace time (ms) */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002304 if (*(args[1]) == 0) {
2305 ha_alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +02002310 if (err == PARSE_TIME_OVER) {
2311 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to grace time, maximum value is 2147483647 ms (~24.8 days).\n",
2312 file, linenum, args[1]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316 else if (err == PARSE_TIME_UNDER) {
2317 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to grace time, minimum non-null value is 1 ms.\n",
2318 file, linenum, args[1]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 else if (err) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002323 ha_alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2324 file, linenum, *err);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328 curproxy->grace = val;
2329 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2330 goto out;
Willy Tarreauab0a5192020-10-09 19:07:01 +02002331
2332 ha_warning("parsing [%s:%d]: the '%s' is deprecated and will be removed in a future version.\n",
2333 file, linenum, args[0]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002334 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002335 else if (strcmp(args[0], "dispatch") == 0) { /* dispatch address */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002336 struct sockaddr_storage *sk;
2337 int port1, port2;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002338
2339 if (curproxy == &defproxy) {
2340 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
2344 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2345 err_code |= ERR_WARN;
2346
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002347 sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL,
2348 &errmsg, NULL, NULL,
2349 PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002350 if (!sk) {
2351 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002356 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2357 goto out;
2358
2359 curproxy->dispatch_addr = *sk;
2360 curproxy->options |= PR_O_DISPATCH;
2361 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002362 else if (strcmp(args[0], "balance") == 0) { /* set balancing with optional algorithm */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002363 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2364 err_code |= ERR_WARN;
2365
2366 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
2367 ha_alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
2371 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002372 else if (strcmp(args[0], "hash-type") == 0) { /* set hashing method */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002373 /**
2374 * The syntax for hash-type config element is
2375 * hash-type {map-based|consistent} [[<algo>] avalanche]
2376 *
2377 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
2378 */
2379 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
2380
2381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2382 err_code |= ERR_WARN;
2383
2384 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2385 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2386 }
2387 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2388 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2389 }
2390 else if (strcmp(args[1], "avalanche") == 0) {
2391 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]);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395 else {
2396 ha_alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400
2401 /* set the hash function to use */
2402 if (!*args[2]) {
2403 /* the default algo is sdbm */
2404 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2405
2406 /* if consistent with no argument, then avalanche modifier is also applied */
2407 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
2408 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2409 } else {
2410 /* set the hash function */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002411 if (strcmp(args[2], "sdbm") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002412 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2413 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002414 else if (strcmp(args[2], "djb2") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002415 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
2416 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002417 else if (strcmp(args[2], "wt6") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002418 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
2419 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002420 else if (strcmp(args[2], "crc32") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002421 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
2422 }
2423 else {
2424 ha_alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428
2429 /* set the hash modifier */
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002430 if (strcmp(args[3], "avalanche") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002431 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2432 }
2433 else if (*args[3]) {
2434 ha_alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 }
2439 }
2440 else if (strcmp(args[0], "hash-balance-factor") == 0) {
2441 if (*(args[1]) == 0) {
2442 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
Willy Tarreau76e84f52019-01-14 16:50:58 +01002446 curproxy->lbprm.hash_balance_factor = atol(args[1]);
2447 if (curproxy->lbprm.hash_balance_factor != 0 && curproxy->lbprm.hash_balance_factor <= 100) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002448 ha_alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452 }
2453 else if (strcmp(args[0], "unique-id-format") == 0) {
2454 if (!*(args[1])) {
2455 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459 if (*(args[2])) {
2460 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464 free(curproxy->conf.uniqueid_format_string);
2465 curproxy->conf.uniqueid_format_string = strdup(args[1]);
2466
2467 free(curproxy->conf.uif_file);
2468 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
2469 curproxy->conf.uif_line = curproxy->conf.args.line;
2470 }
2471
2472 else if (strcmp(args[0], "unique-id-header") == 0) {
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002473 char *copy;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002474 if (!*(args[1])) {
2475 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002479 copy = strdup(args[1]);
2480 if (copy == NULL) {
2481 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486 istfree(&curproxy->header_unique_id);
2487 curproxy->header_unique_id = ist(copy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002488 }
2489
2490 else if (strcmp(args[0], "log-format") == 0) {
2491 if (!*(args[1])) {
2492 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496 if (*(args[2])) {
2497 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2502 char *oldlogformat = "log-format";
2503
2504 if (curproxy->conf.logformat_string == default_http_log_format)
2505 oldlogformat = "option httplog";
2506 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2507 oldlogformat = "option tcplog";
2508 else if (curproxy->conf.logformat_string == clf_http_log_format)
2509 oldlogformat = "option httplog clf";
2510 ha_warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
2511 file, linenum, oldlogformat);
2512 }
2513 if (curproxy->conf.logformat_string != default_http_log_format &&
2514 curproxy->conf.logformat_string != default_tcp_log_format &&
2515 curproxy->conf.logformat_string != clf_http_log_format)
2516 free(curproxy->conf.logformat_string);
2517 curproxy->conf.logformat_string = strdup(args[1]);
2518
2519 free(curproxy->conf.lfs_file);
2520 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2521 curproxy->conf.lfs_line = curproxy->conf.args.line;
2522
2523 /* get a chance to improve log-format error reporting by
2524 * reporting the correct line-number when possible.
2525 */
2526 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2527 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
2528 file, linenum, curproxy->id);
2529 err_code |= ERR_WARN;
2530 }
2531 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002532 else if (strcmp(args[0], "log-format-sd") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002533 if (!*(args[1])) {
2534 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
2537 }
2538 if (*(args[2])) {
2539 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543
2544 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2545 free(curproxy->conf.logformat_sd_string);
2546 curproxy->conf.logformat_sd_string = strdup(args[1]);
2547
2548 free(curproxy->conf.lfsd_file);
2549 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
2550 curproxy->conf.lfsd_line = curproxy->conf.args.line;
2551
2552 /* get a chance to improve log-format-sd error reporting by
2553 * reporting the correct line-number when possible.
2554 */
2555 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2556 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
2557 file, linenum, curproxy->id);
2558 err_code |= ERR_WARN;
2559 }
2560 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002561 else if (strcmp(args[0], "log-tag") == 0) { /* tag to report to syslog */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002562 if (*(args[1]) == 0) {
2563 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
2564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
2566 }
2567 chunk_destroy(&curproxy->log_tag);
Eric Salama7cea6062020-10-02 11:58:19 +02002568 chunk_initlen(&curproxy->log_tag, strdup(args[1]), strlen(args[1]), strlen(args[1]));
2569 if (b_orig(&curproxy->log_tag) == NULL) {
2570 chunk_destroy(&curproxy->log_tag);
2571 ha_alert("parsing [%s:%d]: cannot allocate memory for '%s'.\n", file, linenum, args[0]);
2572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
2574 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002575 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002576 else if (strcmp(args[0], "log") == 0) { /* "no log" or "log ..." */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002577 if (!parse_logsrv(args, &curproxy->logsrvs, (kwm == KWM_NO), &errmsg)) {
2578 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
2579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
2581 }
2582 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002583 else if (strcmp(args[0], "source") == 0) { /* address to which we bind when connecting */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002584 int cur_arg;
2585 int port1, port2;
2586 struct sockaddr_storage *sk;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002587
2588 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2589 err_code |= ERR_WARN;
2590
2591 if (!*args[1]) {
2592 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2593 file, linenum, "source", "usesrc", "interface");
2594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
2596 }
2597
Christopher Faulet31930372019-07-15 10:16:58 +02002598 /* we must first clear any optional default setting */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002599 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2600 free(curproxy->conn_src.iface_name);
2601 curproxy->conn_src.iface_name = NULL;
2602 curproxy->conn_src.iface_len = 0;
2603
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002604 sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL,
2605 &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002606 if (!sk) {
2607 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2608 file, linenum, args[0], args[1], errmsg);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002613 curproxy->conn_src.source_addr = *sk;
2614 curproxy->conn_src.opts |= CO_SRC_BIND;
2615
2616 cur_arg = 2;
2617 while (*(args[cur_arg])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002618 if (strcmp(args[cur_arg], "usesrc") == 0) { /* address to use outside */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002619#if defined(CONFIG_HAP_TRANSPARENT)
2620 if (!*args[cur_arg + 1]) {
2621 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2622 file, linenum, "usesrc");
2623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
2625 }
2626
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002627 if (strcmp(args[cur_arg + 1], "client") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002628 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2629 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002630 } else if (strcmp(args[cur_arg + 1], "clientip") == 0) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002631 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2632 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
2633 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
2634 char *name, *end;
2635
2636 name = args[cur_arg+1] + 7;
Willy Tarreau90807112020-02-25 08:16:33 +01002637 while (isspace((unsigned char)*name))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002638 name++;
2639
2640 end = name;
Willy Tarreau90807112020-02-25 08:16:33 +01002641 while (*end && !isspace((unsigned char)*end) && *end != ',' && *end != ')')
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002642 end++;
2643
2644 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2645 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
Amaury Denoyelle69c5c3a2021-01-26 14:35:22 +01002646 free(curproxy->conn_src.bind_hdr_name);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002647 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
2648 curproxy->conn_src.bind_hdr_len = end - name;
2649 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
2650 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
2651 curproxy->conn_src.bind_hdr_occ = -1;
2652
2653 /* now look for an occurrence number */
Willy Tarreau90807112020-02-25 08:16:33 +01002654 while (isspace((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002655 end++;
2656 if (*end == ',') {
2657 end++;
2658 name = end;
2659 if (*end == '-')
2660 end++;
Willy Tarreau90807112020-02-25 08:16:33 +01002661 while (isdigit((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002662 end++;
2663 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
2664 }
2665
2666 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
2667 ha_alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
2668 " occurrences values smaller than %d.\n",
2669 file, linenum, MAX_HDR_HISTORY);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673 } else {
2674 struct sockaddr_storage *sk;
2675
Willy Tarreau65ec4e32020-09-16 19:17:08 +02002676 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, NULL,
2677 &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002678 if (!sk) {
2679 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2680 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002685 curproxy->conn_src.tproxy_addr = *sk;
2686 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
2687 }
2688 global.last_checks |= LSTCHK_NETADM;
2689#else /* no TPROXY support */
2690 ha_alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
2691 file, linenum, "usesrc");
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694#endif
2695 cur_arg += 2;
2696 continue;
2697 }
2698
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002699 if (strcmp(args[cur_arg], "interface") == 0) { /* specifically bind to this interface */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002700#ifdef SO_BINDTODEVICE
2701 if (!*args[cur_arg + 1]) {
2702 ha_alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2703 file, linenum, args[0]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707 free(curproxy->conn_src.iface_name);
2708 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
2709 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
2710 global.last_checks |= LSTCHK_NETADM;
2711#else
2712 ha_alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2713 file, linenum, args[0], args[cur_arg]);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
2716#endif
2717 cur_arg += 2;
2718 continue;
2719 }
2720 ha_alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2721 file, linenum, args[0], "interface", "usesrc");
2722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
2724 }
2725 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002726 else if (strcmp(args[0], "usesrc") == 0) { /* address to use outside: needs "source" first */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002727 ha_alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2728 file, linenum, "usesrc", "source");
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002732 else if (strcmp(args[0], "cliexp") == 0 || strcmp(args[0], "reqrep") == 0) { /* replace request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002733 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Willy Tarreau262c3f12019-12-17 06:52:51 +01002734 "Use 'http-request replace-path', 'http-request replace-uri' or 'http-request replace-header' instead.\n",
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002735 file, linenum, args[0]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002738 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002739 else if (strcmp(args[0], "reqdel") == 0) { /* delete request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002740 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2741 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002744 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002745 else if (strcmp(args[0], "reqdeny") == 0) { /* deny a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002746 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1. "
2747 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002750 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002751 else if (strcmp(args[0], "reqpass") == 0) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002752 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002755 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002756 else if (strcmp(args[0], "reqallow") == 0) { /* allow a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002757 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2758 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002761 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002762 else if (strcmp(args[0], "reqtarpit") == 0) { /* tarpit a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002763 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2764 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002767 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002768 else if (strcmp(args[0], "reqirep") == 0) { /* replace request header from a regex, ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002769 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2770 "Use 'http-request replace-header' instead.\n", file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002773 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002774 else if (strcmp(args[0], "reqidel") == 0) { /* delete request header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002775 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2776 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
2777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002779 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002780 else if (strcmp(args[0], "reqideny") == 0) { /* deny a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002781 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2782 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002785 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002786 else if (strcmp(args[0], "reqipass") == 0) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002787 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
2788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002790 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002791 else if (strcmp(args[0], "reqiallow") == 0) { /* allow a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002792 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2793 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002796 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002797 else if (strcmp(args[0], "reqitarpit") == 0) { /* tarpit a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002798 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2799 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
2800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002802 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002803 else if (strcmp(args[0], "reqadd") == 0) { /* add request header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002804 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2805 "Use 'http-request add-header' instead.\n", file, linenum, args[0]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002808 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002809 else if (strcmp(args[0], "srvexp") == 0 || strcmp(args[0], "rsprep") == 0) { /* replace response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002810 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2811 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002814 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002815 else if (strcmp(args[0], "rspdel") == 0) { /* delete response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002816 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2817 "Use 'http-response del-header' .\n", file, linenum, args[0]);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002820 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002821 else if (strcmp(args[0], "rspdeny") == 0) { /* block response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002822 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2823 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002826 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002827 else if (strcmp(args[0], "rspirep") == 0) { /* replace response header from a regex ignoring case */
Balvinder Singh Rawatdef595e2020-03-14 12:11:50 +05302828 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002829 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
2830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002832 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002833 else if (strcmp(args[0], "rspidel") == 0) { /* delete response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002834 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2835 "Use 'http-response del-header' instead.\n", file, linenum, args[0]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002838 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002839 else if (strcmp(args[0], "rspideny") == 0) { /* block response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002840 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2841 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002844 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01002845 else if (strcmp(args[0], "rspadd") == 0) { /* add response header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02002846 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
2847 "Use 'http-response add-header' instead.\n", file, linenum, args[0]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002850 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002851 else {
2852 struct cfg_kw_list *kwl;
2853 int index;
2854
2855 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2856 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2857 if (kwl->kw[index].section != CFG_LISTEN)
2858 continue;
2859 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2860 /* prepare error message just in case */
2861 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
2862 if (rc < 0) {
2863 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867 else if (rc > 0) {
2868 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
2869 err_code |= ERR_WARN;
2870 goto out;
2871 }
2872 goto out;
2873 }
2874 }
2875 }
2876
2877 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
2880 }
2881 out:
2882 free(errmsg);
2883 return err_code;
2884}