1 /*
2 * Configuration parser
3 *
4 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13 #ifdef USE_LIBCRYPT
14 /* This is to have crypt() defined on Linux */
15 #define _GNU_SOURCE
16
17 #ifdef USE_CRYPT_H
18 /* some platforms such as Solaris need this */
19 #include <crypt.h>
20 #endif
21 #endif /* USE_LIBCRYPT */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <netdb.h>
27 #include <ctype.h>
28 #include <pwd.h>
29 #include <grp.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35
36 #include <common/cfgparse.h>
37 #include <common/chunk.h>
38 #include <common/config.h>
39 #include <common/errors.h>
40 #include <common/memory.h>
41 #include <common/standard.h>
42 #include <common/time.h>
43 #include <common/uri_auth.h>
44 #include <common/namespace.h>
45 #include <common/hathreads.h>
46
47 #include <types/capture.h>
48 #include <types/filters.h>
49 #include <types/global.h>
50 #include <types/obj_type.h>
51 #include <types/peers.h>
52 #include <types/mailers.h>
53 #include <types/dns.h>
54 #include <types/stats.h>
55
56 #include <proto/acl.h>
57 #include <proto/action.h>
58 #include <proto/auth.h>
59 #include <proto/backend.h>
60 #include <proto/channel.h>
61 #include <proto/checks.h>
62 #include <proto/dns.h>
63 #include <proto/stats.h>
64 #include <proto/filters.h>
65 #include <proto/frontend.h>
66 #include <proto/http_rules.h>
67 #include <proto/lb_chash.h>
68 #include <proto/lb_fas.h>
69 #include <proto/lb_fwlc.h>
70 #include <proto/lb_fwrr.h>
71 #include <proto/lb_map.h>
72 #include <proto/listener.h>
73 #include <proto/log.h>
74 #include <proto/protocol.h>
75 #include <proto/http_ana.h>
76 #include <proto/proxy.h>
77 #include <proto/peers.h>
78 #include <proto/sample.h>
79 #include <proto/session.h>
80 #include <proto/server.h>
81 #include <proto/stream.h>
82 #include <proto/stick_table.h>
83 #include <proto/task.h>
84 #include <proto/tcp_rules.h>
85 #include <proto/connection.h>
86
87
88 /* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93 const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116 };
117
118 /* Used to chain configuration sections definitions. This list
119 * stores struct cfg_section
120 */
121 struct list sections = LIST_HEAD_INIT(sections);
122
123 struct list postparsers = LIST_HEAD_INIT(postparsers);
124
125 char *cursection = NULL;
126 struct proxy defproxy = { }; /* fake proxy used to assign default values on all instances */
127 int cfg_maxpconn = 0; /* # of simultaneous connections per proxy (-N) */
128 int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
129 char *cfg_scope = NULL; /* the current scope during the configuration parsing */
130
131 /* List head of all known configuration keywords */
132 struct cfg_kw_list cfg_keywords = {
133 .list = LIST_HEAD_INIT(cfg_keywords.list)
134 };
135
136 /*
137 * converts <str> to a list of listeners which are dynamically allocated.
138 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
139 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
140 * - <port> is a numerical port from 1 to 65535 ;
141 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
142 * This can be repeated as many times as necessary, separated by a coma.
143 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
144 * not NULL, it must be a valid pointer to either NULL or a freeable area that
145 * will be replaced with an error message.
146 */
str2listener(char * str,struct proxy * curproxy,struct bind_conf * bind_conf,const char * file,int line,char ** err)147 int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
148 {
149 char *next, *dupstr;
150 int port, end;
151
152 next = dupstr = strdup(str);
153
154 while (next && *next) {
155 int inherited = 0;
156 struct sockaddr_storage *ss2;
157 int fd = -1;
158
159 str = next;
160 /* 1) look for the end of the first address */
161 if ((next = strchr(str, ',')) != NULL) {
162 *next++ = 0;
163 }
164
165 ss2 = str2sa_range(str, NULL, &port, &end, err,
166 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
167 NULL, 1);
168 if (!ss2)
169 goto fail;
170
171 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
172 if (!port && !end) {
173 memprintf(err, "missing port number: '%s'\n", str);
174 goto fail;
175 }
176
177 if (!port || !end) {
178 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
179 goto fail;
180 }
181
182 if (port < 1 || port > 65535) {
183 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
184 goto fail;
185 }
186
187 if (end < 1 || end > 65535) {
188 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
189 goto fail;
190 }
191 }
192 else if (ss2->ss_family == AF_UNSPEC) {
193 socklen_t addr_len;
194 inherited = 1;
195
196 /* We want to attach to an already bound fd whose number
197 * is in the addr part of ss2 when cast to sockaddr_in.
198 * Note that by definition there is a single listener.
199 * We still have to determine the address family to
200 * register the correct protocol.
201 */
202 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
203 addr_len = sizeof(*ss2);
204 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
205 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
206 goto fail;
207 }
208
209 port = end = get_host_port(ss2);
210
211 } else if (ss2->ss_family == AF_CUST_SOCKPAIR) {
212 socklen_t addr_len;
213 inherited = 1;
214
215 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
216 addr_len = sizeof(*ss2);
217 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
218 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
219 goto fail;
220 }
221
222 ss2->ss_family = AF_CUST_SOCKPAIR; /* reassign AF_CUST_SOCKPAIR because of getsockname */
223 port = end = 0;
224 }
225
226 /* OK the address looks correct */
227 if (!create_listeners(bind_conf, ss2, port, end, fd, inherited, err)) {
228 memprintf(err, "%s for address '%s'.\n", *err, str);
229 goto fail;
230 }
231 } /* end while(next) */
232 free(dupstr);
233 return 1;
234 fail:
235 free(dupstr);
236 return 0;
237 }
238
239 /*
240 * Report an error in <msg> when there are too many arguments. This version is
241 * intended to be used by keyword parsers so that the message will be included
242 * into the general error message. The index is the current keyword in args.
243 * Return 0 if the number of argument is correct, otherwise build a message and
244 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
245 * message may also be null, it will simply not be produced (useful to check only).
246 * <msg> and <err_code> are only affected on error.
247 */
too_many_args_idx(int maxarg,int index,char ** args,char ** msg,int * err_code)248 int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
249 {
250 int i;
251
252 if (!*args[index + maxarg + 1])
253 return 0;
254
255 if (msg) {
256 *msg = NULL;
257 memprintf(msg, "%s", args[0]);
258 for (i = 1; i <= index; i++)
259 memprintf(msg, "%s %s", *msg, args[i]);
260
261 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
262 }
263 if (err_code)
264 *err_code |= ERR_ALERT | ERR_FATAL;
265
266 return 1;
267 }
268
269 /*
270 * same as too_many_args_idx with a 0 index
271 */
too_many_args(int maxarg,char ** args,char ** msg,int * err_code)272 int too_many_args(int maxarg, char **args, char **msg, int *err_code)
273 {
274 return too_many_args_idx(maxarg, 0, args, msg, err_code);
275 }
276
277 /*
278 * Report a fatal Alert when there is too much arguments
279 * The index is the current keyword in args
280 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
281 * Fill err_code with an ERR_ALERT and an ERR_FATAL
282 */
alertif_too_many_args_idx(int maxarg,int index,const char * file,int linenum,char ** args,int * err_code)283 int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
284 {
285 char *kw = NULL;
286 int i;
287
288 if (!*args[index + maxarg + 1])
289 return 0;
290
291 memprintf(&kw, "%s", args[0]);
292 for (i = 1; i <= index; i++) {
293 memprintf(&kw, "%s %s", kw, args[i]);
294 }
295
296 ha_alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
297 free(kw);
298 *err_code |= ERR_ALERT | ERR_FATAL;
299 return 1;
300 }
301
302 /*
303 * same as alertif_too_many_args_idx with a 0 index
304 */
alertif_too_many_args(int maxarg,const char * file,int linenum,char ** args,int * err_code)305 int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
306 {
307 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
308 }
309
310
311 /* Report it if a request ACL condition uses some keywords that are incompatible
312 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
313 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
314 * will be ignored.
315 */
warnif_cond_conflicts(const struct acl_cond * cond,unsigned int where,const char * file,int line)316 int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
317 {
318 const struct acl *acl;
319 const char *kw;
320
321 if (!cond)
322 return 0;
323
324 acl = acl_cond_conflicts(cond, where);
325 if (acl) {
326 if (acl->name && *acl->name)
327 ha_warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
328 file, line, acl->name, sample_ckp_names(where));
329 else
330 ha_warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
331 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
332 return ERR_WARN;
333 }
334 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
335 return 0;
336
337 if (acl->name && *acl->name)
338 ha_warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
339 file, line, acl->name, kw, sample_ckp_names(where));
340 else
341 ha_warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
342 file, line, kw, sample_ckp_names(where));
343 return ERR_WARN;
344 }
345
346 /* Parse a string representing a process number or a set of processes. It must
347 * be "all", "odd", "even", a number between 1 and <max> or a range with
348 * two such numbers delimited by a dash ('-'). On success, it returns
349 * 0. otherwise it returns 1 with an error message in <err>.
350 *
351 * Note: this function can also be used to parse a thread number or a set of
352 * threads.
353 */
parse_process_number(const char * arg,unsigned long * proc,int max,int * autoinc,char ** err)354 int parse_process_number(const char *arg, unsigned long *proc, int max, int *autoinc, char **err)
355 {
356 if (autoinc) {
357 *autoinc = 0;
358 if (strncmp(arg, "auto:", 5) == 0) {
359 arg += 5;
360 *autoinc = 1;
361 }
362 }
363
364 if (strcmp(arg, "all") == 0)
365 *proc |= ~0UL;
366 else if (strcmp(arg, "odd") == 0)
367 *proc |= ~0UL/3UL; /* 0x555....555 */
368 else if (strcmp(arg, "even") == 0)
369 *proc |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
370 else {
371 const char *p, *dash = NULL;
372 unsigned int low, high;
373
374 for (p = arg; *p; p++) {
375 if (*p == '-' && !dash)
376 dash = p;
377 else if (!isdigit((int)*p)) {
378 memprintf(err, "'%s' is not a valid number/range.", arg);
379 return -1;
380 }
381 }
382
383 low = high = str2uic(arg);
384 if (dash)
385 high = ((!*(dash+1)) ? max : str2uic(dash + 1));
386
387 if (high < low) {
388 unsigned int swap = low;
389 low = high;
390 high = swap;
391 }
392
393 if (low < 1 || low > max || high > max) {
394 memprintf(err, "'%s' is not a valid number/range."
395 " It supports numbers from 1 to %d.\n",
396 arg, max);
397 return 1;
398 }
399
400 for (;low <= high; low++)
401 *proc |= 1UL << (low-1);
402 }
403 *proc &= ~0UL >> (LONGBITS - max);
404
405 return 0;
406 }
407
408 #ifdef USE_CPU_AFFINITY
409 /* Parse cpu sets. Each CPU set is either a unique number between 0 and
410 * <LONGBITS> or a range with two such numbers delimited by a dash
411 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
412 * returns 0. otherwise it returns 1 with an error message in <err>.
413 */
parse_cpu_set(const char ** args,unsigned long * cpu_set,char ** err)414 unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
415 {
416 int cur_arg = 0;
417
418 *cpu_set = 0;
419 while (*args[cur_arg]) {
420 char *dash;
421 unsigned int low, high;
422
423 if (!isdigit((int)*args[cur_arg])) {
424 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
425 return -1;
426 }
427
428 low = high = str2uic(args[cur_arg]);
429 if ((dash = strchr(args[cur_arg], '-')) != NULL)
430 high = ((!*(dash+1)) ? LONGBITS-1 : str2uic(dash + 1));
431
432 if (high < low) {
433 unsigned int swap = low;
434 low = high;
435 high = swap;
436 }
437
438 if (high >= LONGBITS) {
439 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
440 return 1;
441 }
442
443 while (low <= high)
444 *cpu_set |= 1UL << low++;
445
446 cur_arg++;
447 }
448 return 0;
449 }
450 #endif
451
init_default_instance()452 void init_default_instance()
453 {
454 init_new_proxy(&defproxy);
455 defproxy.mode = PR_MODE_TCP;
456 defproxy.state = PR_STNEW;
457 defproxy.maxconn = cfg_maxpconn;
458 defproxy.conn_retries = CONN_RETRIES;
459 defproxy.redispatch_after = 0;
460 defproxy.options = PR_O_REUSE_SAFE;
461 defproxy.max_out_conns = MAX_SRV_LIST;
462
463 defproxy.defsrv.check.inter = DEF_CHKINTR;
464 defproxy.defsrv.check.fastinter = 0;
465 defproxy.defsrv.check.downinter = 0;
466 defproxy.defsrv.agent.inter = DEF_CHKINTR;
467 defproxy.defsrv.agent.fastinter = 0;
468 defproxy.defsrv.agent.downinter = 0;
469 defproxy.defsrv.check.rise = DEF_RISETIME;
470 defproxy.defsrv.check.fall = DEF_FALLTIME;
471 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
472 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
473 defproxy.defsrv.check.port = 0;
474 defproxy.defsrv.agent.port = 0;
475 defproxy.defsrv.maxqueue = 0;
476 defproxy.defsrv.minconn = 0;
477 defproxy.defsrv.maxconn = 0;
478 defproxy.defsrv.max_reuse = -1;
479 defproxy.defsrv.max_idle_conns = -1;
480 defproxy.defsrv.pool_purge_delay = 5000;
481 defproxy.defsrv.slowstart = 0;
482 defproxy.defsrv.onerror = DEF_HANA_ONERR;
483 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
484 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
485
486 defproxy.email_alert.level = LOG_ALERT;
487 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
488 }
489
490 /* Allocate and initialize the frontend of a "peers" section found in
491 * file <file> at line <linenum> with <id> as ID.
492 * Return 0 if succeeded, -1 if not.
493 * Note that this function may be called from "default-server"
494 * or "peer" lines.
495 */
init_peers_frontend(const char * file,int linenum,const char * id,struct peers * peers)496 static int init_peers_frontend(const char *file, int linenum,
497 const char *id, struct peers *peers)
498 {
499 struct proxy *p;
500
501 if (peers->peers_fe) {
502 p = peers->peers_fe;
503 goto out;
504 }
505
506 p = calloc(1, sizeof *p);
507 if (!p) {
508 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
509 return -1;
510 }
511
512 init_new_proxy(p);
513 peers_setup_frontend(p);
514 p->parent = peers;
515 /* Finally store this frontend. */
516 peers->peers_fe = p;
517
518 out:
519 if (id && !p->id)
520 p->id = strdup(id);
521 free(p->conf.file);
522 p->conf.args.file = p->conf.file = strdup(file);
523 if (linenum != -1)
524 p->conf.args.line = p->conf.line = linenum;
525
526 return 0;
527 }
528
529 /* Only change ->file, ->line and ->arg struct bind_conf member values
530 * if already present.
531 */
bind_conf_uniq_alloc(struct proxy * p,const char * file,int line,const char * arg,struct xprt_ops * xprt)532 static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p,
533 const char *file, int line,
534 const char *arg, struct xprt_ops *xprt)
535 {
536 struct bind_conf *bind_conf;
537
538 if (!LIST_ISEMPTY(&p->conf.bind)) {
539 bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), by_fe);
540 free(bind_conf->file);
541 bind_conf->file = strdup(file);
542 bind_conf->line = line;
543 if (arg) {
544 free(bind_conf->arg);
545 bind_conf->arg = strdup(arg);
546 }
547 }
548 else {
549 bind_conf = bind_conf_alloc(p, file, line, arg, xprt);
550 }
551
552 return bind_conf;
553 }
554
555 /*
556 * Allocate a new struct peer parsed at line <linenum> in file <file>
557 * to be added to <peers>.
558 * Returns the new allocated structure if succeeded, NULL if not.
559 */
cfg_peers_add_peer(struct peers * peers,const char * file,int linenum,const char * id,int local)560 static struct peer *cfg_peers_add_peer(struct peers *peers,
561 const char *file, int linenum,
562 const char *id, int local)
563 {
564 struct peer *p;
565
566 p = calloc(1, sizeof *p);
567 if (!p) {
568 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
569 return NULL;
570 }
571
572 /* the peers are linked backwards first */
573 peers->count++;
574 p->next = peers->remote;
575 peers->remote = p;
576 p->conf.file = strdup(file);
577 p->conf.line = linenum;
578 p->last_change = now.tv_sec;
579 p->xprt = xprt_get(XPRT_RAW);
580 p->sock_init_arg = NULL;
581 HA_SPIN_INIT(&p->lock);
582 if (id)
583 p->id = strdup(id);
584 if (local) {
585 p->local = 1;
586 peers->local = p;
587 }
588
589 return p;
590 }
591
592 /*
593 * Parse a line in a <listen>, <frontend> or <backend> section.
594 * Returns the error code, 0 if OK, or any combination of :
595 * - ERR_ABORT: must abort ASAP
596 * - ERR_FATAL: we can continue parsing but not start the service
597 * - ERR_WARN: a warning has been emitted
598 * - ERR_ALERT: an alert has been emitted
599 * Only the two first ones can stop processing, the two others are just
600 * indicators.
601 */
cfg_parse_peers(const char * file,int linenum,char ** args,int kwm)602 int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
603 {
604 static struct peers *curpeers = NULL;
605 struct peer *newpeer = NULL;
606 const char *err;
607 struct bind_conf *bind_conf;
608 struct listener *l;
609 int err_code = 0;
610 char *errmsg = NULL;
611 static int bind_line, peer_line;
612
613 if (strcmp(args[0], "bind") == 0 || strcmp(args[0], "default-bind") == 0) {
614 int cur_arg;
615 static int kws_dumped;
616 struct bind_conf *bind_conf;
617 struct bind_kw *kw;
618
619 cur_arg = 1;
620
621 if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
622 err_code |= ERR_ALERT | ERR_ABORT;
623 goto out;
624 }
625
626 bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum,
627 NULL, xprt_get(XPRT_RAW));
628 if (*args[0] == 'b') {
629 struct listener *l;
630
631 if (peer_line) {
632 ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635 }
636
637 if (!str2listener(args[1], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
638 if (errmsg && *errmsg) {
639 indent_msg(&errmsg, 2);
640 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
641 }
642 else
643 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
644 file, linenum, args[0], args[1], args[2]);
645 err_code |= ERR_FATAL;
646 goto out;
647 }
648 l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind);
649 l->maxaccept = 1;
650 l->accept = session_accept_fd;
651 l->analysers |= curpeers->peers_fe->fe_req_ana;
652 l->default_target = curpeers->peers_fe->default_target;
653 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
654 global.maxsock++; /* for the listening socket */
655
656 bind_line = 1;
657 if (cfg_peers->local) {
658 newpeer = cfg_peers->local;
659 }
660 else {
661 /* This peer is local.
662 * Note that we do not set the peer ID. This latter is initialized
663 * when parsing "peer" or "server" line.
664 */
665 newpeer = cfg_peers_add_peer(curpeers, file, linenum, NULL, 1);
666 if (!newpeer) {
667 err_code |= ERR_ALERT | ERR_ABORT;
668 goto out;
669 }
670 }
671 newpeer->addr = l->addr;
672 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
673 cur_arg++;
674 }
675
676 while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) {
677 int ret;
678
679 ret = kw->parse(args, cur_arg, curpeers->peers_fe, bind_conf, &errmsg);
680 err_code |= ret;
681 if (ret) {
682 if (errmsg && *errmsg) {
683 indent_msg(&errmsg, 2);
684 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
685 }
686 else
687 ha_alert("parsing [%s:%d]: error encountered while processing '%s'\n",
688 file, linenum, args[cur_arg]);
689 if (ret & ERR_FATAL)
690 goto out;
691 }
692 cur_arg += 1 + kw->skip;
693 }
694 if (*args[cur_arg] != 0) {
695 char *kws = NULL;
696
697 if (!kws_dumped) {
698 kws_dumped = 1;
699 bind_dump_kws(&kws);
700 indent_msg(&kws, 4);
701 }
702 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section.%s%s\n",
703 file, linenum, args[cur_arg], cursection,
704 kws ? " Registered keywords :" : "", kws ? kws: "");
705 free(kws);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 }
710 else if (strcmp(args[0], "default-server") == 0) {
711 if (init_peers_frontend(file, -1, NULL, curpeers) != 0) {
712 err_code |= ERR_ALERT | ERR_ABORT;
713 goto out;
714 }
715 err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL, 0, 1, 1);
716 }
717 else if (strcmp(args[0], "log") == 0) {
718 if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
719 err_code |= ERR_ALERT | ERR_ABORT;
720 goto out;
721 }
722 if (!parse_logsrv(args, &curpeers->peers_fe->logsrvs, (kwm == KWM_NO), &errmsg)) {
723 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
726 }
727 }
728 else if (strcmp(args[0], "peers") == 0) { /* new peers section */
729 /* Initialize these static variables when entering a new "peers" section*/
730 bind_line = peer_line = 0;
731 if (!*args[1]) {
732 ha_alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
733 err_code |= ERR_ALERT | ERR_ABORT;
734 goto out;
735 }
736
737 if (alertif_too_many_args(1, file, linenum, args, &err_code))
738 goto out;
739
740 err = invalid_char(args[1]);
741 if (err) {
742 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
743 file, linenum, *err, args[0], args[1]);
744 err_code |= ERR_ALERT | ERR_ABORT;
745 goto out;
746 }
747
748 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
749 /*
750 * If there are two proxies with the same name only following
751 * combinations are allowed:
752 */
753 if (strcmp(curpeers->id, args[1]) == 0) {
754 ha_alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
755 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 }
758 }
759
760 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
761 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
762 err_code |= ERR_ALERT | ERR_ABORT;
763 goto out;
764 }
765
766 curpeers->next = cfg_peers;
767 cfg_peers = curpeers;
768 curpeers->conf.file = strdup(file);
769 curpeers->conf.line = linenum;
770 curpeers->last_change = now.tv_sec;
771 curpeers->id = strdup(args[1]);
772 curpeers->state = PR_STNEW;
773 }
774 else if (strcmp(args[0], "peer") == 0 ||
775 strcmp(args[0], "server") == 0) { /* peer or server definition */
776 int local_peer, peer;
777
778 peer = *args[0] == 'p';
779 local_peer = !strcmp(args[1], localpeer);
780 /* The local peer may have already partially been parsed on a "bind" line. */
781 if (*args[0] == 'p') {
782 if (bind_line) {
783 ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 peer_line = 1;
788 }
789 if (cfg_peers->local && !cfg_peers->local->id && local_peer) {
790 /* The local peer has already been initialized on a "bind" line.
791 * Let's use it and store its ID.
792 */
793 newpeer = cfg_peers->local;
794 newpeer->id = strdup(localpeer);
795 }
796 else {
797 if (local_peer && cfg_peers->local) {
798 ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d. %s\n",
799 file, linenum, args[0], args[1],
800 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line, cfg_peers->local->id);
801 err_code |= ERR_FATAL;
802 goto out;
803 }
804 newpeer = cfg_peers_add_peer(curpeers, file, linenum, args[1], local_peer);
805 if (!newpeer) {
806 err_code |= ERR_ALERT | ERR_ABORT;
807 goto out;
808 }
809 }
810
811 /* Line number and peer ID are updated only if this peer is the local one. */
812 if (init_peers_frontend(file,
813 newpeer->local ? linenum: -1,
814 newpeer->local ? newpeer->id : NULL,
815 curpeers) != 0) {
816 err_code |= ERR_ALERT | ERR_ABORT;
817 goto out;
818 }
819
820 /* This initializes curpeer->peers->peers_fe->srv.
821 * The server address is parsed only if we are parsing a "peer" line,
822 * or if we are parsing a "server" line and the current peer is not the local one.
823 */
824 err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL, peer || !local_peer, 1, 1);
825 if (!curpeers->peers_fe->srv) {
826 /* Remove the newly allocated peer. */
827 if (newpeer != curpeers->local) {
828 struct peer *p;
829
830 p = curpeers->remote;
831 curpeers->remote = curpeers->remote->next;
832 free(p->id);
833 free(p);
834 }
835 goto out;
836 }
837
838 /* If the peer address has just been parsed, let's copy it to <newpeer>
839 * and initializes ->proto.
840 */
841 if (peer || !local_peer) {
842 newpeer->addr = curpeers->peers_fe->srv->addr;
843 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
844 }
845
846 newpeer->xprt = xprt_get(XPRT_RAW);
847 newpeer->sock_init_arg = NULL;
848 HA_SPIN_INIT(&newpeer->lock);
849
850 newpeer->srv = curpeers->peers_fe->srv;
851 if (!newpeer->local)
852 goto out;
853
854 /* The lines above are reserved to "peer" lines. */
855 if (*args[0] == 's')
856 goto out;
857
858 bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
859
860 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
861 if (errmsg && *errmsg) {
862 indent_msg(&errmsg, 2);
863 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
864 }
865 else
866 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
867 file, linenum, args[0], args[1], args[2]);
868 err_code |= ERR_FATAL;
869 goto out;
870 }
871
872 l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind);
873 l->maxaccept = 1;
874 l->accept = session_accept_fd;
875 l->analysers |= curpeers->peers_fe->fe_req_ana;
876 l->default_target = curpeers->peers_fe->default_target;
877 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
878 global.maxsock++; /* for the listening socket */
879 }
880 else if (!strcmp(args[0], "table")) {
881 struct stktable *t, *other;
882 char *id;
883 size_t prefix_len;
884
885 /* Line number and peer ID are updated only if this peer is the local one. */
886 if (init_peers_frontend(file, -1, NULL, curpeers) != 0) {
887 err_code |= ERR_ALERT | ERR_ABORT;
888 goto out;
889 }
890
891 other = stktable_find_by_name(args[1]);
892 if (other) {
893 ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
894 file, linenum, args[1],
895 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
896 other->proxy ? other->id : other->peers.p->id,
897 other->conf.file, other->conf.line);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901
902 /* Build the stick-table name, concatenating the "peers" section name
903 * followed by a '/' character and the table name argument.
904 */
905 chunk_reset(&trash);
906 if (!chunk_strcpy(&trash, curpeers->id)) {
907 ha_alert("parsing [%s:%d]: '%s %s' : stick-table name too long.\n",
908 file, linenum, args[0], args[1]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912
913 prefix_len = trash.data;
914 if (!chunk_memcat(&trash, "/", 1) || !chunk_strcat(&trash, args[1])) {
915 ha_alert("parsing [%s:%d]: '%s %s' : stick-table name too long.\n",
916 file, linenum, args[0], args[1]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920
921 t = calloc(1, sizeof *t);
922 id = strdup(trash.area);
923 if (!t || !id) {
924 ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
925 file, linenum, args[0], args[1]);
926 free(t);
927 free(id);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931
932 err_code |= parse_stick_table(file, linenum, args, t, id, id + prefix_len, curpeers);
933 if (err_code & ERR_FATAL) {
934 free(t);
935 free(id);
936 goto out;
937 }
938
939 stktable_store_name(t);
940 t->next = stktables_list;
941 stktables_list = t;
942 }
943 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
944 curpeers->state = PR_STSTOPPED;
945 }
946 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
947 curpeers->state = PR_STNEW;
948 }
949 else if (*args[0] != 0) {
950 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954
955 out:
956 free(errmsg);
957 return err_code;
958 }
959
960 /*
961 * Parse a <resolvers> section.
962 * Returns the error code, 0 if OK, or any combination of :
963 * - ERR_ABORT: must abort ASAP
964 * - ERR_FATAL: we can continue parsing but not start the service
965 * - ERR_WARN: a warning has been emitted
966 * - ERR_ALERT: an alert has been emitted
967 * Only the two first ones can stop processing, the two others are just
968 * indicators.
969 */
cfg_parse_resolvers(const char * file,int linenum,char ** args,int kwm)970 int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
971 {
972 static struct dns_resolvers *curr_resolvers = NULL;
973 const char *err;
974 int err_code = 0;
975 char *errmsg = NULL;
976
977 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
978 if (!*args[1]) {
979 ha_alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
980 err_code |= ERR_ALERT | ERR_ABORT;
981 goto out;
982 }
983
984 err = invalid_char(args[1]);
985 if (err) {
986 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
987 file, linenum, *err, args[0], args[1]);
988 err_code |= ERR_ALERT | ERR_ABORT;
989 goto out;
990 }
991
992 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
993 /* Error if two resolvers owns the same name */
994 if (strcmp(curr_resolvers->id, args[1]) == 0) {
995 ha_alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
996 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
997 err_code |= ERR_ALERT | ERR_ABORT;
998 }
999 }
1000
1001 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
1002 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1003 err_code |= ERR_ALERT | ERR_ABORT;
1004 goto out;
1005 }
1006
1007 /* default values */
1008 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
1009 curr_resolvers->conf.file = strdup(file);
1010 curr_resolvers->conf.line = linenum;
1011 curr_resolvers->id = strdup(args[1]);
1012 curr_resolvers->query_ids = EB_ROOT;
1013 /* default maximum response size */
1014 curr_resolvers->accepted_payload_size = 512;
1015 /* default hold period for nx, other, refuse and timeout is 30s */
1016 curr_resolvers->hold.nx = 30000;
1017 curr_resolvers->hold.other = 30000;
1018 curr_resolvers->hold.refused = 30000;
1019 curr_resolvers->hold.timeout = 30000;
1020 curr_resolvers->hold.obsolete = 0;
1021 /* default hold period for valid is 10s */
1022 curr_resolvers->hold.valid = 10000;
1023 curr_resolvers->timeout.resolve = 1000;
1024 curr_resolvers->timeout.retry = 1000;
1025 curr_resolvers->resolve_retries = 3;
1026 curr_resolvers->nb_nameservers = 0;
1027 LIST_INIT(&curr_resolvers->nameservers);
1028 LIST_INIT(&curr_resolvers->resolutions.curr);
1029 LIST_INIT(&curr_resolvers->resolutions.wait);
1030 HA_SPIN_INIT(&curr_resolvers->lock);
1031 }
1032 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
1033 struct dns_nameserver *newnameserver = NULL;
1034 struct sockaddr_storage *sk;
1035 int port1, port2;
1036 struct protocol *proto;
1037
1038 if (!*args[2]) {
1039 ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1040 file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044
1045 err = invalid_char(args[1]);
1046 if (err) {
1047 ha_alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1048 file, linenum, *err, args[1]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052
1053 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
1054 /* Error if two resolvers owns the same name */
1055 if (strcmp(newnameserver->id, args[1]) == 0) {
1056 ha_alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
1057 file, linenum, args[1], newnameserver->conf.file, newnameserver->conf.line);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 }
1060 }
1061
1062 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
1063 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1064 err_code |= ERR_ALERT | ERR_ABORT;
1065 goto out;
1066 }
1067
1068 /* the nameservers are linked backward first */
1069 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
1070 newnameserver->resolvers = curr_resolvers;
1071 newnameserver->conf.file = strdup(file);
1072 newnameserver->conf.line = linenum;
1073 newnameserver->id = strdup(args[1]);
1074
1075 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
1076 if (!sk) {
1077 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081
1082 proto = protocol_by_family(sk->ss_family);
1083 if (!proto || !proto->connect) {
1084 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1085 file, linenum, args[0], args[1]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089
1090 if (port1 != port2) {
1091 ha_alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1092 file, linenum, args[0], args[1], args[2]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096
1097 if (!port1 && !port2) {
1098 ha_alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
1099 file, linenum, args[0], args[1]);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
1102 }
1103
1104 newnameserver->addr = *sk;
1105 }
1106 else if (strcmp(args[0], "parse-resolv-conf") == 0) {
1107 struct dns_nameserver *newnameserver = NULL;
1108 const char *whitespace = "\r\n\t ";
1109 char *resolv_line = NULL;
1110 int resolv_linenum = 0;
1111 FILE *f = NULL;
1112 char *address = NULL;
1113 struct sockaddr_storage *sk = NULL;
1114 struct protocol *proto;
1115 int duplicate_name = 0;
1116
1117 if ((resolv_line = malloc(sizeof(*resolv_line) * LINESIZE)) == NULL) {
1118 ha_alert("parsing [%s:%d] : out of memory.\n",
1119 file, linenum);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto resolv_out;
1122 }
1123
1124 if ((f = fopen("/etc/resolv.conf", "r")) == NULL) {
1125 ha_alert("parsing [%s:%d] : failed to open /etc/resolv.conf.\n",
1126 file, linenum);
1127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto resolv_out;
1129 }
1130
1131 sk = calloc(1, sizeof(*sk));
1132 if (sk == NULL) {
1133 ha_alert("parsing [/etc/resolv.conf:%d] : out of memory.\n",
1134 resolv_linenum);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto resolv_out;
1137 }
1138
1139 while (fgets(resolv_line, LINESIZE, f) != NULL) {
1140 resolv_linenum++;
1141 if (strncmp(resolv_line, "nameserver", 10) != 0)
1142 continue;
1143
1144 address = strtok(resolv_line + 10, whitespace);
1145 if (address == resolv_line + 10)
1146 continue;
1147
1148 if (address == NULL) {
1149 ha_warning("parsing [/etc/resolv.conf:%d] : nameserver line is missing address.\n",
1150 resolv_linenum);
1151 err_code |= ERR_WARN;
1152 continue;
1153 }
1154
1155 duplicate_name = 0;
1156 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
1157 if (strcmp(newnameserver->id, address) == 0) {
1158 ha_warning("Parsing [/etc/resolv.conf:%d] : generated name for /etc/resolv.conf nameserver '%s' conflicts with another nameserver (declared at %s:%d), it appears to be a duplicate and will be excluded.\n",
1159 resolv_linenum, address, newnameserver->conf.file, newnameserver->conf.line);
1160 err_code |= ERR_WARN;
1161 duplicate_name = 1;
1162 }
1163 }
1164
1165 if (duplicate_name)
1166 continue;
1167
1168 memset(sk, 0, sizeof(*sk));
1169 if (!str2ip2(address, sk, 1)) {
1170 ha_warning("parsing [/etc/resolv.conf:%d] : address '%s' could not be recognized, nameserver will be excluded.\n",
1171 resolv_linenum, address);
1172 err_code |= ERR_WARN;
1173 continue;
1174 }
1175
1176 set_host_port(sk, 53);
1177
1178 proto = protocol_by_family(sk->ss_family);
1179 if (!proto || !proto->connect) {
1180 ha_warning("parsing [/etc/resolv.conf:%d] : '%s' : connect() not supported for this address family.\n",
1181 resolv_linenum, address);
1182 err_code |= ERR_WARN;
1183 continue;
1184 }
1185
1186 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
1187 ha_alert("parsing [/etc/resolv.conf:%d] : out of memory.\n", resolv_linenum);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto resolv_out;
1190 }
1191
1192 newnameserver->conf.file = strdup("/etc/resolv.conf");
1193 if (newnameserver->conf.file == NULL) {
1194 ha_alert("parsing [/etc/resolv.conf:%d] : out of memory.\n", resolv_linenum);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 free(newnameserver);
1197 goto resolv_out;
1198 }
1199
1200 newnameserver->id = strdup(address);
1201 if (newnameserver->id == NULL) {
1202 ha_alert("parsing [/etc/resolv.conf:%d] : out of memory.\n", resolv_linenum);
1203 err_code |= ERR_ALERT | ERR_FATAL;
1204 free((char *)newnameserver->conf.file);
1205 free(newnameserver);
1206 goto resolv_out;
1207 }
1208
1209 newnameserver->resolvers = curr_resolvers;
1210 newnameserver->conf.line = resolv_linenum;
1211 newnameserver->addr = *sk;
1212
1213 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
1214 }
1215
1216 resolv_out:
1217 free(sk);
1218 free(resolv_line);
1219 if (f != NULL)
1220 fclose(f);
1221 }
1222 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
1223 const char *res;
1224 unsigned int time;
1225
1226 if (!*args[2]) {
1227 ha_alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
1228 file, linenum, args[0]);
1229 ha_alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
1232 }
1233 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
1234 if (res == PARSE_TIME_OVER) {
1235 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
1236 file, linenum, args[1], args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 else if (res == PARSE_TIME_UNDER) {
1241 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
1242 file, linenum, args[1], args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246 else if (res) {
1247 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1248 file, linenum, *res, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 if (strcmp(args[1], "nx") == 0)
1253 curr_resolvers->hold.nx = time;
1254 else if (strcmp(args[1], "other") == 0)
1255 curr_resolvers->hold.other = time;
1256 else if (strcmp(args[1], "refused") == 0)
1257 curr_resolvers->hold.refused = time;
1258 else if (strcmp(args[1], "timeout") == 0)
1259 curr_resolvers->hold.timeout = time;
1260 else if (strcmp(args[1], "valid") == 0)
1261 curr_resolvers->hold.valid = time;
1262 else if (strcmp(args[1], "obsolete") == 0)
1263 curr_resolvers->hold.obsolete = time;
1264 else {
1265 ha_alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
1266 file, linenum, args[0], args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 }
1272 else if (strcmp(args[0], "accepted_payload_size") == 0) {
1273 int i = 0;
1274
1275 if (!*args[1]) {
1276 ha_alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
1277 file, linenum, args[0]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281
1282 i = atoi(args[1]);
1283 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
1284 ha_alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
1285 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289
1290 curr_resolvers->accepted_payload_size = i;
1291 }
1292 else if (strcmp(args[0], "resolution_pool_size") == 0) {
1293 ha_alert("parsing [%s:%d] : '%s' directive is not supported anymore (it never appeared in a stable release).\n",
1294 file, linenum, args[0]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298 else if (strcmp(args[0], "resolve_retries") == 0) {
1299 if (!*args[1]) {
1300 ha_alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
1301 file, linenum, args[0]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 curr_resolvers->resolve_retries = atoi(args[1]);
1306 }
1307 else if (strcmp(args[0], "timeout") == 0) {
1308 if (!*args[1]) {
1309 ha_alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
1310 file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 else if (strcmp(args[1], "retry") == 0 ||
1315 strcmp(args[1], "resolve") == 0) {
1316 const char *res;
1317 unsigned int tout;
1318
1319 if (!*args[2]) {
1320 ha_alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
1321 file, linenum, args[0], args[1]);
1322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
1324 }
1325 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
1326 if (res == PARSE_TIME_OVER) {
1327 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s %s>, maximum value is 2147483647 ms (~24.8 days).\n",
1328 file, linenum, args[2], args[0], args[1]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 else if (res == PARSE_TIME_UNDER) {
1333 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s %s>, minimum non-null value is 1 ms.\n",
1334 file, linenum, args[2], args[0], args[1]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 else if (res) {
1339 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
1340 file, linenum, *res, args[0], args[1]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344 if (args[1][2] == 't')
1345 curr_resolvers->timeout.retry = tout;
1346 else
1347 curr_resolvers->timeout.resolve = tout;
1348 }
1349 else {
1350 ha_alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
1351 file, linenum, args[0], args[1]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 }
1356 else if (*args[0] != 0) {
1357 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1358 err_code |= ERR_ALERT | ERR_FATAL;
1359 goto out;
1360 }
1361
1362 out:
1363 free(errmsg);
1364 return err_code;
1365 }
1366
1367 /*
1368 * Parse a line in a <listen>, <frontend> or <backend> section.
1369 * Returns the error code, 0 if OK, or any combination of :
1370 * - ERR_ABORT: must abort ASAP
1371 * - ERR_FATAL: we can continue parsing but not start the service
1372 * - ERR_WARN: a warning has been emitted
1373 * - ERR_ALERT: an alert has been emitted
1374 * Only the two first ones can stop processing, the two others are just
1375 * indicators.
1376 */
cfg_parse_mailers(const char * file,int linenum,char ** args,int kwm)1377 int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1378 {
1379 static struct mailers *curmailers = NULL;
1380 struct mailer *newmailer = NULL;
1381 const char *err;
1382 int err_code = 0;
1383 char *errmsg = NULL;
1384
1385 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1386 if (!*args[1]) {
1387 ha_alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1388 err_code |= ERR_ALERT | ERR_ABORT;
1389 goto out;
1390 }
1391
1392 err = invalid_char(args[1]);
1393 if (err) {
1394 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1395 file, linenum, *err, args[0], args[1]);
1396 err_code |= ERR_ALERT | ERR_ABORT;
1397 goto out;
1398 }
1399
1400 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1401 /*
1402 * If there are two proxies with the same name only following
1403 * combinations are allowed:
1404 */
1405 if (strcmp(curmailers->id, args[1]) == 0) {
1406 ha_alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
1407 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1408 err_code |= ERR_ALERT | ERR_FATAL;
1409 }
1410 }
1411
1412 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
1413 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1414 err_code |= ERR_ALERT | ERR_ABORT;
1415 goto out;
1416 }
1417
1418 curmailers->next = mailers;
1419 mailers = curmailers;
1420 curmailers->conf.file = strdup(file);
1421 curmailers->conf.line = linenum;
1422 curmailers->id = strdup(args[1]);
1423 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
1424 * But need enough time so that timeouts don't occur
1425 * during tcp procssing. For now just us an arbitrary default. */
1426 }
1427 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1428 struct sockaddr_storage *sk;
1429 int port1, port2;
1430 struct protocol *proto;
1431
1432 if (!*args[2]) {
1433 ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1434 file, linenum, args[0]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
1437 }
1438
1439 err = invalid_char(args[1]);
1440 if (err) {
1441 ha_alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1442 file, linenum, *err, args[1]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446
1447 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
1448 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1449 err_code |= ERR_ALERT | ERR_ABORT;
1450 goto out;
1451 }
1452
1453 /* the mailers are linked backwards first */
1454 curmailers->count++;
1455 newmailer->next = curmailers->mailer_list;
1456 curmailers->mailer_list = newmailer;
1457 newmailer->mailers = curmailers;
1458 newmailer->conf.file = strdup(file);
1459 newmailer->conf.line = linenum;
1460
1461 newmailer->id = strdup(args[1]);
1462
1463 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
1464 if (!sk) {
1465 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469
1470 proto = protocol_by_family(sk->ss_family);
1471 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
1472 ha_alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
1473 file, linenum, args[0], args[1]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
1476 }
1477
1478 if (port1 != port2) {
1479 ha_alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1480 file, linenum, args[0], args[1], args[2]);
1481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485 if (!port1) {
1486 ha_alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1487 file, linenum, args[0], args[1], args[2]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
1490 }
1491
1492 newmailer->addr = *sk;
1493 newmailer->proto = proto;
1494 newmailer->xprt = xprt_get(XPRT_RAW);
1495 newmailer->sock_init_arg = NULL;
1496 }
1497 else if (strcmp(args[0], "timeout") == 0) {
1498 if (!*args[1]) {
1499 ha_alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
1500 file, linenum, args[0]);
1501 err_code |= ERR_ALERT | ERR_FATAL;
1502 goto out;
1503 }
1504 else if (strcmp(args[1], "mail") == 0) {
1505 const char *res;
1506 unsigned int timeout_mail;
1507 if (!*args[2]) {
1508 ha_alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
1509 file, linenum, args[0], args[1]);
1510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
1512 }
1513 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
1514 if (res == PARSE_TIME_OVER) {
1515 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s %s>, maximum value is 2147483647 ms (~24.8 days).\n",
1516 file, linenum, args[2], args[0], args[1]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 else if (res == PARSE_TIME_UNDER) {
1521 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s %s>, minimum non-null value is 1 ms.\n",
1522 file, linenum, args[2], args[0], args[1]);
1523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
1525 }
1526 else if (res) {
1527 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
1528 file, linenum, *res, args[0], args[1]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532 curmailers->timeout.mail = timeout_mail;
1533 } else {
1534 ha_alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
1535 file, linenum, args[0], args[1]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539 }
1540 else if (*args[0] != 0) {
1541 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
1544 }
1545
1546 out:
1547 free(errmsg);
1548 return err_code;
1549 }
1550
free_email_alert(struct proxy * p)1551 void free_email_alert(struct proxy *p)
1552 {
1553 free(p->email_alert.mailers.name);
1554 p->email_alert.mailers.name = NULL;
1555 free(p->email_alert.from);
1556 p->email_alert.from = NULL;
1557 free(p->email_alert.to);
1558 p->email_alert.to = NULL;
1559 free(p->email_alert.myhostname);
1560 p->email_alert.myhostname = NULL;
1561 }
1562
1563
1564 int
cfg_parse_netns(const char * file,int linenum,char ** args,int kwm)1565 cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
1566 {
1567 #ifdef USE_NS
1568 const char *err;
1569 const char *item = args[0];
1570
1571 if (!strcmp(item, "namespace_list")) {
1572 return 0;
1573 }
1574 else if (!strcmp(item, "namespace")) {
1575 size_t idx = 1;
1576 const char *current;
1577 while (*(current = args[idx++])) {
1578 err = invalid_char(current);
1579 if (err) {
1580 ha_alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
1581 file, linenum, *err, item, current);
1582 return ERR_ALERT | ERR_FATAL;
1583 }
1584
1585 if (netns_store_lookup(current, strlen(current))) {
1586 ha_alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
1587 file, linenum, current);
1588 return ERR_ALERT | ERR_FATAL;
1589 }
1590 if (!netns_store_insert(current)) {
1591 ha_alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
1592 file, linenum, current);
1593 return ERR_ALERT | ERR_FATAL;
1594 }
1595 }
1596 }
1597
1598 return 0;
1599 #else
1600 ha_alert("parsing [%s:%d]: namespace support is not compiled in.",
1601 file, linenum);
1602 return ERR_ALERT | ERR_FATAL;
1603 #endif
1604 }
1605
1606 int
cfg_parse_users(const char * file,int linenum,char ** args,int kwm)1607 cfg_parse_users(const char *file, int linenum, char **args, int kwm)
1608 {
1609
1610 int err_code = 0;
1611 const char *err;
1612
1613 if (!strcmp(args[0], "userlist")) { /* new userlist */
1614 struct userlist *newul;
1615
1616 if (!*args[1]) {
1617 ha_alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
1618 file, linenum, args[0]);
1619 err_code |= ERR_ALERT | ERR_FATAL;
1620 goto out;
1621 }
1622 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1623 goto out;
1624
1625 err = invalid_char(args[1]);
1626 if (err) {
1627 ha_alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
1628 file, linenum, *err, args[0], args[1]);
1629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
1631 }
1632
1633 for (newul = userlist; newul; newul = newul->next)
1634 if (!strcmp(newul->name, args[1])) {
1635 ha_warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
1636 file, linenum, args[1]);
1637 err_code |= ERR_WARN;
1638 goto out;
1639 }
1640
1641 newul = calloc(1, sizeof(*newul));
1642 if (!newul) {
1643 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1644 err_code |= ERR_ALERT | ERR_ABORT;
1645 goto out;
1646 }
1647
1648 newul->name = strdup(args[1]);
1649 if (!newul->name) {
1650 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1651 err_code |= ERR_ALERT | ERR_ABORT;
1652 free(newul);
1653 goto out;
1654 }
1655
1656 newul->next = userlist;
1657 userlist = newul;
1658
1659 } else if (!strcmp(args[0], "group")) { /* new group */
1660 int cur_arg;
1661 const char *err;
1662 struct auth_groups *ag;
1663
1664 if (!*args[1]) {
1665 ha_alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
1666 file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669 }
1670
1671 err = invalid_char(args[1]);
1672 if (err) {
1673 ha_alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
1674 file, linenum, *err, args[0], args[1]);
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
1677 }
1678
1679 if (!userlist)
1680 goto out;
1681
1682 for (ag = userlist->groups; ag; ag = ag->next)
1683 if (!strcmp(ag->name, args[1])) {
1684 ha_warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
1685 file, linenum, args[1], userlist->name);
1686 err_code |= ERR_ALERT;
1687 goto out;
1688 }
1689
1690 ag = calloc(1, sizeof(*ag));
1691 if (!ag) {
1692 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1693 err_code |= ERR_ALERT | ERR_ABORT;
1694 goto out;
1695 }
1696
1697 ag->name = strdup(args[1]);
1698 if (!ag->name) {
1699 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1700 err_code |= ERR_ALERT | ERR_ABORT;
1701 free(ag);
1702 goto out;
1703 }
1704
1705 cur_arg = 2;
1706
1707 while (*args[cur_arg]) {
1708 if (!strcmp(args[cur_arg], "users")) {
1709 ag->groupusers = strdup(args[cur_arg + 1]);
1710 cur_arg += 2;
1711 continue;
1712 } else {
1713 ha_alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
1714 file, linenum, args[0]);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 free(ag->groupusers);
1717 free(ag->name);
1718 free(ag);
1719 goto out;
1720 }
1721 }
1722
1723 ag->next = userlist->groups;
1724 userlist->groups = ag;
1725
1726 } else if (!strcmp(args[0], "user")) { /* new user */
1727 struct auth_users *newuser;
1728 int cur_arg;
1729
1730 if (!*args[1]) {
1731 ha_alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
1732 file, linenum, args[0]);
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736 if (!userlist)
1737 goto out;
1738
1739 for (newuser = userlist->users; newuser; newuser = newuser->next)
1740 if (!strcmp(newuser->user, args[1])) {
1741 ha_warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
1742 file, linenum, args[1], userlist->name);
1743 err_code |= ERR_ALERT;
1744 goto out;
1745 }
1746
1747 newuser = calloc(1, sizeof(*newuser));
1748 if (!newuser) {
1749 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1750 err_code |= ERR_ALERT | ERR_ABORT;
1751 goto out;
1752 }
1753
1754 newuser->user = strdup(args[1]);
1755
1756 newuser->next = userlist->users;
1757 userlist->users = newuser;
1758
1759 cur_arg = 2;
1760
1761 while (*args[cur_arg]) {
1762 if (!strcmp(args[cur_arg], "password")) {
1763 #ifdef USE_LIBCRYPT
1764 if (!crypt("", args[cur_arg + 1])) {
1765 ha_alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
1766 file, linenum, newuser->user);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770 #else
1771 ha_warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
1772 file, linenum);
1773 err_code |= ERR_ALERT;
1774 #endif
1775 newuser->pass = strdup(args[cur_arg + 1]);
1776 cur_arg += 2;
1777 continue;
1778 } else if (!strcmp(args[cur_arg], "insecure-password")) {
1779 newuser->pass = strdup(args[cur_arg + 1]);
1780 newuser->flags |= AU_O_INSECURE;
1781 cur_arg += 2;
1782 continue;
1783 } else if (!strcmp(args[cur_arg], "groups")) {
1784 newuser->u.groups_names = strdup(args[cur_arg + 1]);
1785 cur_arg += 2;
1786 continue;
1787 } else {
1788 ha_alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
1789 file, linenum, args[0]);
1790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793 }
1794 } else {
1795 ha_alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 }
1798
1799 out:
1800 return err_code;
1801 }
1802
1803 int
cfg_parse_scope(const char * file,int linenum,char * line)1804 cfg_parse_scope(const char *file, int linenum, char *line)
1805 {
1806 char *beg, *end, *scope = NULL;
1807 int err_code = 0;
1808 const char *err;
1809
1810 beg = line + 1;
1811 end = strchr(beg, ']');
1812
1813 /* Detect end of scope declaration */
1814 if (!end || end == beg) {
1815 ha_alert("parsing [%s:%d] : empty scope name is forbidden.\n",
1816 file, linenum);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 /* Get scope name and check its validity */
1822 scope = my_strndup(beg, end-beg);
1823 err = invalid_char(scope);
1824 if (err) {
1825 ha_alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
1826 file, linenum, *err);
1827 err_code |= ERR_ALERT | ERR_ABORT;
1828 goto out;
1829 }
1830
1831 /* Be sure to have a scope declaration alone on its line */
1832 line = end+1;
1833 while (isspace((unsigned char)*line))
1834 line++;
1835 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
1836 ha_alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
1837 file, linenum, *line);
1838 err_code |= ERR_ALERT | ERR_ABORT;
1839 goto out;
1840 }
1841
1842 /* We have a valid scope declaration, save it */
1843 free(cfg_scope);
1844 cfg_scope = scope;
1845 scope = NULL;
1846
1847 out:
1848 free(scope);
1849 return err_code;
1850 }
1851
1852 int
cfg_parse_track_sc_num(unsigned int * track_sc_num,const char * arg,const char * end,char ** errmsg)1853 cfg_parse_track_sc_num(unsigned int *track_sc_num,
1854 const char *arg, const char *end, char **errmsg)
1855 {
1856 const char *p;
1857 unsigned int num;
1858
1859 p = arg;
1860 num = read_uint64(&arg, end);
1861
1862 if (arg != end) {
1863 memprintf(errmsg, "Wrong track-sc number '%s'", p);
1864 return -1;
1865 }
1866
1867 if (num >= MAX_SESS_STKCTR) {
1868 memprintf(errmsg, "%u track-sc number exceeding "
1869 "%d (MAX_SESS_STKCTR-1) value", num, MAX_SESS_STKCTR - 1);
1870 return -1;
1871 }
1872
1873 *track_sc_num = num;
1874 return 0;
1875 }
1876
1877 /*
1878 * This function reads and parses the configuration file given in the argument.
1879 * Returns the error code, 0 if OK, or any combination of :
1880 * - ERR_ABORT: must abort ASAP
1881 * - ERR_FATAL: we can continue parsing but not start the service
1882 * - ERR_WARN: a warning has been emitted
1883 * - ERR_ALERT: an alert has been emitted
1884 * Only the two first ones can stop processing, the two others are just
1885 * indicators.
1886 */
readcfgfile(const char * file)1887 int readcfgfile(const char *file)
1888 {
1889 char *thisline;
1890 int linesize = LINESIZE;
1891 FILE *f;
1892 int linenum = 0;
1893 int err_code = 0;
1894 struct cfg_section *cs = NULL, *pcs = NULL;
1895 struct cfg_section *ics;
1896 int readbytes = 0;
1897
1898 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
1899 ha_alert("parsing [%s] : out of memory.\n", file);
1900 return -1;
1901 }
1902
1903 if ((f=fopen(file,"r")) == NULL) {
1904 free(thisline);
1905 return -1;
1906 }
1907
1908 next_line:
1909 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
1910 int arg, kwm = KWM_STD;
1911 char *end;
1912 char *args[MAX_LINE_ARGS + 1];
1913 char *line = thisline;
1914 int dquote = 0; /* double quote */
1915 int squote = 0; /* simple quote */
1916
1917 linenum++;
1918
1919 end = line + strlen(line);
1920
1921 if (end-line == linesize-1 && *(end-1) != '\n') {
1922 /* Check if we reached the limit and the last char is not \n.
1923 * Watch out for the last line without the terminating '\n'!
1924 */
1925 char *newline;
1926 int newlinesize = linesize * 2;
1927
1928 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
1929 if (newline == NULL) {
1930 ha_alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
1931 file, linenum);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 linenum--;
1934 continue;
1935 }
1936
1937 readbytes = linesize - 1;
1938 linesize = newlinesize;
1939 thisline = newline;
1940 linenum--;
1941 continue;
1942 }
1943
1944 readbytes = 0;
1945
1946 /* skip leading spaces */
1947 while (isspace((unsigned char)*line))
1948 line++;
1949
1950
1951 if (*line == '[') {/* This is the beginning if a scope */
1952 err_code |= cfg_parse_scope(file, linenum, line);
1953 goto next_line;
1954 }
1955
1956 arg = 0;
1957 args[arg] = line;
1958
1959 while (*line && arg < MAX_LINE_ARGS) {
1960 if (*line == '"' && !squote) { /* double quote outside single quotes */
1961 if (dquote)
1962 dquote = 0;
1963 else
1964 dquote = 1;
1965 memmove(line, line + 1, end - line);
1966 end--;
1967 }
1968 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
1969 if (squote)
1970 squote = 0;
1971 else
1972 squote = 1;
1973 memmove(line, line + 1, end - line);
1974 end--;
1975 }
1976 else if (*line == '\\' && !squote) {
1977 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
1978 * C equivalent value. Other combinations left unchanged (eg: \1).
1979 */
1980 int skip = 0;
1981 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
1982 *line = line[1];
1983 skip = 1;
1984 }
1985 else if (line[1] == 'r') {
1986 *line = '\r';
1987 skip = 1;
1988 }
1989 else if (line[1] == 'n') {
1990 *line = '\n';
1991 skip = 1;
1992 }
1993 else if (line[1] == 't') {
1994 *line = '\t';
1995 skip = 1;
1996 }
1997 else if (line[1] == 'x') {
1998 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
1999 unsigned char hex1, hex2;
2000 hex1 = toupper(line[2]) - '0';
2001 hex2 = toupper(line[3]) - '0';
2002 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2003 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2004 *line = (hex1<<4) + hex2;
2005 skip = 3;
2006 }
2007 else {
2008 ha_alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto next_line;
2011 }
2012 } else if (line[1] == '"') {
2013 *line = '"';
2014 skip = 1;
2015 } else if (line[1] == '\'') {
2016 *line = '\'';
2017 skip = 1;
2018 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
2019 *line = '$';
2020 skip = 1;
2021 }
2022 if (skip) {
2023 memmove(line + 1, line + 1 + skip, end - (line + skip));
2024 end -= skip;
2025 }
2026 line++;
2027 }
2028 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
2029 /* end of string, end of loop */
2030 *line = 0;
2031 break;
2032 }
2033 else if (!squote && !dquote && isspace((unsigned char)*line)) {
2034 /* a non-escaped space is an argument separator */
2035 *line++ = '\0';
2036 while (isspace((unsigned char)*line))
2037 line++;
2038 args[++arg] = line;
2039 }
2040 else if (dquote && *line == '$') {
2041 /* environment variables are evaluated inside double quotes */
2042 char *var_beg;
2043 char *var_end;
2044 char save_char;
2045 char *value;
2046 int val_len;
2047 int newlinesize;
2048 int braces = 0;
2049
2050 var_beg = line + 1;
2051 var_end = var_beg;
2052
2053 if (*var_beg == '{') {
2054 var_beg++;
2055 var_end++;
2056 braces = 1;
2057 }
2058
2059 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
2060 ha_alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
2061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto next_line; /* skip current line */
2063 }
2064
2065 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
2066 var_end++;
2067
2068 save_char = *var_end;
2069 *var_end = '\0';
2070 value = getenv(var_beg);
2071 *var_end = save_char;
2072 val_len = value ? strlen(value) : 0;
2073
2074 if (braces) {
2075 if (*var_end == '}') {
2076 var_end++;
2077 braces = 0;
2078 } else {
2079 ha_alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
2080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto next_line; /* skip current line */
2082 }
2083 }
2084
2085 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
2086
2087 /* if not enough space in thisline */
2088 if (newlinesize > linesize) {
2089 char *newline;
2090
2091 newline = realloc(thisline, newlinesize * sizeof(*thisline));
2092 if (newline == NULL) {
2093 ha_alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto next_line; /* slip current line */
2096 }
2097 /* recompute pointers if realloc returns a new pointer */
2098 if (newline != thisline) {
2099 int i;
2100 int diff;
2101
2102 for (i = 0; i <= arg; i++) {
2103 diff = args[i] - thisline;
2104 args[i] = newline + diff;
2105 }
2106
2107 diff = var_end - thisline;
2108 var_end = newline + diff;
2109 diff = end - thisline;
2110 end = newline + diff;
2111 diff = line - thisline;
2112 line = newline + diff;
2113 thisline = newline;
2114 }
2115 linesize = newlinesize;
2116 }
2117
2118 /* insert value inside the line */
2119 memmove(line + val_len, var_end, end - var_end + 1);
2120 memcpy(line, value, val_len);
2121 end += val_len - (var_end - line);
2122 line += val_len;
2123 }
2124 else {
2125 line++;
2126 }
2127 }
2128
2129 if (dquote) {
2130 ha_alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 }
2133
2134 if (squote) {
2135 ha_alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
2136 err_code |= ERR_ALERT | ERR_FATAL;
2137 }
2138
2139 /* empty line */
2140 if (!**args)
2141 continue;
2142
2143 if (*line) {
2144 /* we had to stop due to too many args.
2145 * Let's terminate the string, print the offending part then cut the
2146 * last arg.
2147 */
2148 while (*line && *line != '#' && *line != '\n' && *line != '\r')
2149 line++;
2150 *line = '\0';
2151
2152 ha_alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
2153 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 args[arg] = line;
2156 }
2157
2158 /* zero out remaining args and ensure that at least one entry
2159 * is zeroed out.
2160 */
2161 while (++arg <= MAX_LINE_ARGS) {
2162 args[arg] = line;
2163 }
2164
2165 /* check for keyword modifiers "no" and "default" */
2166 if (!strcmp(args[0], "no")) {
2167 char *tmp;
2168
2169 kwm = KWM_NO;
2170 tmp = args[0];
2171 for (arg=0; *args[arg+1]; arg++)
2172 args[arg] = args[arg+1]; // shift args after inversion
2173 *tmp = '\0'; // fix the next arg to \0
2174 args[arg] = tmp;
2175 }
2176 else if (!strcmp(args[0], "default")) {
2177 kwm = KWM_DEF;
2178 for (arg=0; *args[arg+1]; arg++)
2179 args[arg] = args[arg+1]; // shift args after inversion
2180 }
2181
2182 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 &&
2183 strcmp(args[0], "log") != 0 && strcmp(args[0], "busy-polling") != 0 &&
2184 strcmp(args[0], "set-dumpable") != 0 && strcmp(args[0], "strict-limits") != 0) {
2185 ha_alert("parsing [%s:%d]: negation/default currently "
2186 "supported only for options, log, busy-polling, "
2187 "set-dumpable and strict-limits.\n", file, linenum);
2188 err_code |= ERR_ALERT | ERR_FATAL;
2189 }
2190
2191 /* detect section start */
2192 list_for_each_entry(ics, §ions, list) {
2193 if (strcmp(args[0], ics->section_name) == 0) {
2194 cursection = ics->section_name;
2195 pcs = cs;
2196 cs = ics;
2197 break;
2198 }
2199 }
2200
2201 if (pcs && pcs->post_section_parser) {
2202 err_code |= pcs->post_section_parser();
2203 if (err_code & ERR_ABORT)
2204 goto err;
2205 }
2206 pcs = NULL;
2207
2208 if (!cs) {
2209 ha_alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 } else {
2212 err_code |= cs->section_parser(file, linenum, args, kwm);
2213 if (err_code & ERR_ABORT)
2214 goto err;
2215 }
2216 }
2217
2218 if (cs && cs->post_section_parser)
2219 err_code |= cs->post_section_parser();
2220
2221 err:
2222 free(cfg_scope);
2223 cfg_scope = NULL;
2224 cursection = NULL;
2225 free(thisline);
2226 fclose(f);
2227 return err_code;
2228 }
2229
2230 /* This function propagates processes from frontend <from> to backend <to> so
2231 * that it is always guaranteed that a backend pointed to by a frontend is
2232 * bound to all of its processes. After that, if the target is a "listen"
2233 * instance, the function recursively descends the target's own targets along
2234 * default_backend and use_backend rules. Since the bits are
2235 * checked first to ensure that <to> is already bound to all processes of
2236 * <from>, there is no risk of looping and we ensure to follow the shortest
2237 * path to the destination.
2238 *
2239 * It is possible to set <to> to NULL for the first call so that the function
2240 * takes care of visiting the initial frontend in <from>.
2241 *
2242 * It is important to note that the function relies on the fact that all names
2243 * have already been resolved.
2244 */
propagate_processes(struct proxy * from,struct proxy * to)2245 void propagate_processes(struct proxy *from, struct proxy *to)
2246 {
2247 struct switching_rule *rule;
2248
2249 if (to) {
2250 /* check whether we need to go down */
2251 if (from->bind_proc &&
2252 (from->bind_proc & to->bind_proc) == from->bind_proc)
2253 return;
2254
2255 if (!from->bind_proc && !to->bind_proc)
2256 return;
2257
2258 to->bind_proc = from->bind_proc ?
2259 (to->bind_proc | from->bind_proc) : 0;
2260
2261 /* now propagate down */
2262 from = to;
2263 }
2264
2265 if (!(from->cap & PR_CAP_FE))
2266 return;
2267
2268 if (from->state == PR_STSTOPPED)
2269 return;
2270
2271 /* default_backend */
2272 if (from->defbe.be)
2273 propagate_processes(from, from->defbe.be);
2274
2275 /* use_backend */
2276 list_for_each_entry(rule, &from->switching_rules, list) {
2277 if (rule->dynamic)
2278 continue;
2279 to = rule->be.backend;
2280 propagate_processes(from, to);
2281 }
2282 }
2283
2284 /*
2285 * Returns the error code, 0 if OK, or any combination of :
2286 * - ERR_ABORT: must abort ASAP
2287 * - ERR_FATAL: we can continue parsing but not start the service
2288 * - ERR_WARN: a warning has been emitted
2289 * - ERR_ALERT: an alert has been emitted
2290 * Only the two first ones can stop processing, the two others are just
2291 * indicators.
2292 */
check_config_validity()2293 int check_config_validity()
2294 {
2295 int cfgerr = 0;
2296 struct proxy *curproxy = NULL;
2297 struct stktable *t;
2298 struct server *newsrv = NULL;
2299 int err_code = 0;
2300 unsigned int next_pxid = 1;
2301 struct bind_conf *bind_conf;
2302 char *err;
2303 struct cfg_postparser *postparser;
2304 struct dns_resolvers *curr_resolvers = NULL;
2305
2306 bind_conf = NULL;
2307 /*
2308 * Now, check for the integrity of all that we have collected.
2309 */
2310
2311 /* will be needed further to delay some tasks */
2312 tv_update_date(0,1);
2313
2314 if (!global.tune.max_http_hdr)
2315 global.tune.max_http_hdr = MAX_HTTP_HDR;
2316
2317 if (!global.tune.cookie_len)
2318 global.tune.cookie_len = CAPTURE_LEN;
2319
2320 if (!global.tune.requri_len)
2321 global.tune.requri_len = REQURI_LEN;
2322
2323 if (!global.nbthread) {
2324 /* nbthread not set, thus automatic. In this case, and only if
2325 * running on a single process, we enable the same number of
2326 * threads as the number of CPUs the process is bound to. This
2327 * allows to easily control the number of threads using taskset.
2328 */
2329 global.nbthread = 1;
2330 #if defined(USE_THREAD)
2331 if (global.nbproc == 1)
2332 global.nbthread = thread_cpus_enabled_at_boot;
2333 all_threads_mask = nbits(global.nbthread);
2334 #endif
2335 }
2336
2337 if (global.nbproc > 1 && global.nbthread > 1) {
2338 ha_alert("config : cannot enable multiple processes if multiple threads are configured. Please use either nbproc or nbthread but not both.\n");
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342
2343 pool_head_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
2344
2345 pool_head_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
2346
2347 /* Post initialisation of the users and groups lists. */
2348 err_code = userlist_postinit();
2349 if (err_code != ERR_NONE)
2350 goto out;
2351
2352 /* first, we will invert the proxy list order */
2353 curproxy = NULL;
2354 while (proxies_list) {
2355 struct proxy *next;
2356
2357 next = proxies_list->next;
2358 proxies_list->next = curproxy;
2359 curproxy = proxies_list;
2360 if (!next)
2361 break;
2362 proxies_list = next;
2363 }
2364
2365 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
2366 struct switching_rule *rule;
2367 struct server_rule *srule;
2368 struct sticking_rule *mrule;
2369 struct act_rule *arule;
2370 struct logsrv *tmplogsrv;
2371 unsigned int next_id;
2372 int nbproc;
2373
2374 if (curproxy->uuid < 0) {
2375 /* proxy ID not set, use automatic numbering with first
2376 * spare entry starting with next_pxid.
2377 */
2378 next_pxid = get_next_id(&used_proxy_id, next_pxid);
2379 curproxy->conf.id.key = curproxy->uuid = next_pxid;
2380 eb32_insert(&used_proxy_id, &curproxy->conf.id);
2381 }
2382 next_pxid++;
2383
2384
2385 if (curproxy->state == PR_STSTOPPED) {
2386 /* ensure we don't keep listeners uselessly bound */
2387 stop_proxy(curproxy);
2388 if (curproxy->table) {
2389 free((void *)curproxy->table->peers.name);
2390 curproxy->table->peers.p = NULL;
2391 }
2392 continue;
2393 }
2394
2395 /* Check multi-process mode compatibility for the current proxy */
2396
2397 if (curproxy->bind_proc) {
2398 /* an explicit bind-process was specified, let's check how many
2399 * processes remain.
2400 */
2401 nbproc = my_popcountl(curproxy->bind_proc);
2402
2403 curproxy->bind_proc &= all_proc_mask;
2404 if (!curproxy->bind_proc && nbproc == 1) {
2405 ha_warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
2406 curproxy->bind_proc = 1;
2407 }
2408 else if (!curproxy->bind_proc && nbproc > 1) {
2409 ha_warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
2410 curproxy->bind_proc = 0;
2411 }
2412 }
2413
2414 /* check and reduce the bind-proc of each listener */
2415 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
2416 unsigned long mask;
2417
2418 /* HTTP frontends with "h2" as ALPN/NPN will work in
2419 * HTTP/2 and absolutely require buffers 16kB or larger.
2420 */
2421 #ifdef USE_OPENSSL
2422 if (curproxy->mode == PR_MODE_HTTP && global.tune.bufsize < 16384) {
2423 #ifdef OPENSSL_NPN_NEGOTIATED
2424 /* check NPN */
2425 if (bind_conf->ssl_conf.npn_str && strstr(bind_conf->ssl_conf.npn_str, "\002h2")) {
2426 ha_alert("config : HTTP frontend '%s' enables HTTP/2 via NPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
2427 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
2428 cfgerr++;
2429 }
2430 #endif
2431 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2432 /* check ALPN */
2433 if (bind_conf->ssl_conf.alpn_str && strstr(bind_conf->ssl_conf.alpn_str, "\002h2")) {
2434 ha_alert("config : HTTP frontend '%s' enables HTTP/2 via ALPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
2435 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
2436 cfgerr++;
2437 }
2438 #endif
2439 } /* HTTP && bufsize < 16384 */
2440 #endif
2441
2442 /* detect and address thread affinity inconsistencies */
2443 mask = thread_mask(bind_conf->bind_thread);
2444 if (!(mask & all_threads_mask)) {
2445 unsigned long new_mask = 0;
2446
2447 while (mask) {
2448 new_mask |= mask & all_threads_mask;
2449 mask >>= global.nbthread;
2450 }
2451
2452 bind_conf->bind_thread = new_mask;
2453 ha_warning("Proxy '%s': the thread range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to thread numbers out of the range defined by the global 'nbthread' directive. The thread numbers were remapped to existing threads instead (mask 0x%lx).\n",
2454 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line, new_mask);
2455 }
2456
2457 /* detect process and nbproc affinity inconsistencies */
2458 mask = proc_mask(bind_conf->bind_proc) & proc_mask(curproxy->bind_proc);
2459 if (!(mask & all_proc_mask)) {
2460 mask = proc_mask(curproxy->bind_proc) & all_proc_mask;
2461 nbproc = my_popcountl(bind_conf->bind_proc);
2462 bind_conf->bind_proc = proc_mask(bind_conf->bind_proc) & mask;
2463
2464 if (!bind_conf->bind_proc && nbproc == 1) {
2465 ha_warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
2466 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
2467 bind_conf->bind_proc = mask & ~(mask - 1);
2468 }
2469 else if (!bind_conf->bind_proc && nbproc > 1) {
2470 ha_warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
2471 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
2472 bind_conf->bind_proc = 0;
2473 }
2474 }
2475 }
2476
2477 switch (curproxy->mode) {
2478 case PR_MODE_HEALTH:
2479 cfgerr += proxy_cfg_ensure_no_http(curproxy);
2480 if (!(curproxy->cap & PR_CAP_FE)) {
2481 ha_alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
2482 proxy_type_str(curproxy), curproxy->id);
2483 cfgerr++;
2484 }
2485
2486 if (curproxy->srv != NULL)
2487 ha_warning("config : servers will be ignored for %s '%s'.\n",
2488 proxy_type_str(curproxy), curproxy->id);
2489 break;
2490
2491 case PR_MODE_TCP:
2492 cfgerr += proxy_cfg_ensure_no_http(curproxy);
2493 break;
2494
2495 case PR_MODE_HTTP:
2496 curproxy->http_needed = 1;
2497 break;
2498
2499 case PR_MODE_CLI:
2500 cfgerr += proxy_cfg_ensure_no_http(curproxy);
2501 break;
2502 }
2503
2504 if (curproxy != global.stats_fe && (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
2505 ha_warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
2506 proxy_type_str(curproxy), curproxy->id);
2507 err_code |= ERR_WARN;
2508 }
2509
2510 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
2511 if (curproxy->lbprm.algo & BE_LB_KIND) {
2512 if (curproxy->options & PR_O_TRANSP) {
2513 ha_alert("config : %s '%s' cannot use both transparent and balance mode.\n",
2514 proxy_type_str(curproxy), curproxy->id);
2515 cfgerr++;
2516 }
2517 #ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2518 else if (curproxy->srv == NULL) {
2519 ha_alert("config : %s '%s' needs at least 1 server in balance mode.\n",
2520 proxy_type_str(curproxy), curproxy->id);
2521 cfgerr++;
2522 }
2523 #endif
2524 else if (curproxy->options & PR_O_DISPATCH) {
2525 ha_warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
2526 proxy_type_str(curproxy), curproxy->id);
2527 err_code |= ERR_WARN;
2528 }
2529 }
2530 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
2531 /* If no LB algo is set in a backend, and we're not in
2532 * transparent mode, dispatch mode nor proxy mode, we
2533 * want to use balance roundrobin by default.
2534 */
2535 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2536 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
2537 }
2538 }
2539
2540 if (curproxy->options & PR_O_DISPATCH)
2541 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
2542 else if (curproxy->options & PR_O_HTTP_PROXY)
2543 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
2544 else if (curproxy->options & PR_O_TRANSP)
2545 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
2546
2547 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
2548 if (curproxy->options & PR_O_DISABLE404) {
2549 ha_warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2550 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2551 err_code |= ERR_WARN;
2552 curproxy->options &= ~PR_O_DISABLE404;
2553 }
2554 if (curproxy->options2 & PR_O2_CHK_SNDST) {
2555 ha_warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2556 "send-state", proxy_type_str(curproxy), curproxy->id);
2557 err_code |= ERR_WARN;
2558 curproxy->options &= ~PR_O2_CHK_SNDST;
2559 }
2560 }
2561
2562 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
2563 if (!global.external_check) {
2564 ha_alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
2565 curproxy->id, "option external-check");
2566 cfgerr++;
2567 }
2568 if (!curproxy->check_command) {
2569 ha_alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
2570 curproxy->id, "option external-check");
2571 cfgerr++;
2572 }
2573 }
2574
2575 if (curproxy->email_alert.set) {
2576 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
2577 ha_warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
2578 "'email-alert from', 'email-alert level' 'email-alert mailers', "
2579 "'email-alert myhostname', or 'email-alert to' "
2580 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
2581 "to be present).\n",
2582 proxy_type_str(curproxy), curproxy->id);
2583 err_code |= ERR_WARN;
2584 free_email_alert(curproxy);
2585 }
2586 if (!curproxy->email_alert.myhostname)
2587 curproxy->email_alert.myhostname = strdup(hostname);
2588 }
2589
2590 if (curproxy->check_command) {
2591 int clear = 0;
2592 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
2593 ha_warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
2594 "external-check command", proxy_type_str(curproxy), curproxy->id);
2595 err_code |= ERR_WARN;
2596 clear = 1;
2597 }
2598 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
2599 ha_alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
2600 curproxy->id, "external-check command");
2601 cfgerr++;
2602 }
2603 if (clear) {
2604 free(curproxy->check_command);
2605 curproxy->check_command = NULL;
2606 }
2607 }
2608
2609 if (curproxy->check_path) {
2610 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
2611 ha_warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
2612 "external-check path", proxy_type_str(curproxy), curproxy->id);
2613 err_code |= ERR_WARN;
2614 free(curproxy->check_path);
2615 curproxy->check_path = NULL;
2616 }
2617 }
2618
2619 /* if a default backend was specified, let's find it */
2620 if (curproxy->defbe.name) {
2621 struct proxy *target;
2622
2623 target = proxy_be_by_name(curproxy->defbe.name);
2624 if (!target) {
2625 ha_alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2626 curproxy->id, curproxy->defbe.name);
2627 cfgerr++;
2628 } else if (target == curproxy) {
2629 ha_alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2630 curproxy->id, curproxy->defbe.name);
2631 cfgerr++;
2632 } else if (target->mode != curproxy->mode &&
2633 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
2634
2635 ha_alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
2636 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
2637 curproxy->conf.file, curproxy->conf.line,
2638 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
2639 target->conf.file, target->conf.line);
2640 cfgerr++;
2641 } else {
2642 free(curproxy->defbe.name);
2643 curproxy->defbe.be = target;
2644 /* Emit a warning if this proxy also has some servers */
2645 if (curproxy->srv) {
2646 ha_warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
2647 curproxy->id);
2648 err_code |= ERR_WARN;
2649 }
2650 }
2651 }
2652
2653 /* find the target proxy for 'use_backend' rules */
2654 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2655 struct proxy *target;
2656 struct logformat_node *node;
2657 char *pxname;
2658
2659 /* Try to parse the string as a log format expression. If the result
2660 * of the parsing is only one entry containing a simple string, then
2661 * it's a standard string corresponding to a static rule, thus the
2662 * parsing is cancelled and be.name is restored to be resolved.
2663 */
2664 pxname = rule->be.name;
2665 LIST_INIT(&rule->be.expr);
2666 curproxy->conf.args.ctx = ARGC_UBK;
2667 curproxy->conf.args.file = rule->file;
2668 curproxy->conf.args.line = rule->line;
2669 err = NULL;
2670 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
2671 ha_alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
2672 rule->file, rule->line, pxname, err);
2673 free(err);
2674 cfgerr++;
2675 continue;
2676 }
2677 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
2678
2679 if (!LIST_ISEMPTY(&rule->be.expr)) {
2680 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
2681 rule->dynamic = 1;
2682 free(pxname);
2683 continue;
2684 }
2685 /* Only one element in the list, a simple string: free the expression and
2686 * fall back to static rule
2687 */
2688 LIST_DEL(&node->list);
2689 free(node->arg);
2690 free(node);
2691 }
2692
2693 rule->dynamic = 0;
2694 rule->be.name = pxname;
2695
2696 target = proxy_be_by_name(rule->be.name);
2697 if (!target) {
2698 ha_alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2699 curproxy->id, rule->be.name);
2700 cfgerr++;
2701 } else if (target == curproxy) {
2702 ha_alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2703 curproxy->id, rule->be.name);
2704 cfgerr++;
2705 } else if (target->mode != curproxy->mode &&
2706 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
2707
2708 ha_alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
2709 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
2710 curproxy->conf.file, curproxy->conf.line,
2711 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
2712 target->conf.file, target->conf.line);
2713 cfgerr++;
2714 } else {
2715 free((void *)rule->be.name);
2716 rule->be.backend = target;
2717 }
2718 }
2719
2720 /* find the target server for 'use_server' rules */
2721 list_for_each_entry(srule, &curproxy->server_rules, list) {
2722 struct server *target = findserver(curproxy, srule->srv.name);
2723
2724 if (!target) {
2725 ha_alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
2726 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
2727 cfgerr++;
2728 continue;
2729 }
2730 free((void *)srule->srv.name);
2731 srule->srv.ptr = target;
2732 }
2733
2734 /* find the target table for 'stick' rules */
2735 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
2736 struct stktable *target;
2737
2738 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
2739 if (mrule->flags & STK_IS_STORE)
2740 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
2741
2742 if (mrule->table.name)
2743 target = stktable_find_by_name(mrule->table.name);
2744 else
2745 target = curproxy->table;
2746
2747 if (!target) {
2748 ha_alert("Proxy '%s': unable to find stick-table '%s'.\n",
2749 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
2750 cfgerr++;
2751 }
2752 else if (!stktable_compatible_sample(mrule->expr, target->type)) {
2753 ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
2754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
2755 cfgerr++;
2756 }
2757 else if (target->proxy && curproxy->bind_proc & ~target->proxy->bind_proc) {
2758 ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
2759 curproxy->id, target->id, curproxy->id);
2760 cfgerr++;
2761 }
2762 else {
2763 free((void *)mrule->table.name);
2764 mrule->table.t = target;
2765 stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
2766 stktable_alloc_data_type(target, STKTABLE_DT_SERVER_NAME, NULL);
2767 if (!in_proxies_list(target->proxies_list, curproxy)) {
2768 curproxy->next_stkt_ref = target->proxies_list;
2769 target->proxies_list = curproxy;
2770 }
2771 }
2772 }
2773
2774 /* find the target table for 'store response' rules */
2775 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
2776 struct stktable *target;
2777
2778 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
2779
2780 if (mrule->table.name)
2781 target = stktable_find_by_name(mrule->table.name);
2782 else
2783 target = curproxy->table;
2784
2785 if (!target) {
2786 ha_alert("Proxy '%s': unable to find store table '%s'.\n",
2787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
2788 cfgerr++;
2789 }
2790 else if (!stktable_compatible_sample(mrule->expr, target->type)) {
2791 ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
2792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
2793 cfgerr++;
2794 }
2795 else if (target->proxy && (curproxy->bind_proc & ~target->proxy->bind_proc)) {
2796 ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
2797 curproxy->id, target->id, curproxy->id);
2798 cfgerr++;
2799 }
2800 else {
2801 free((void *)mrule->table.name);
2802 mrule->table.t = target;
2803 stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
2804 stktable_alloc_data_type(target, STKTABLE_DT_SERVER_NAME, NULL);
2805 if (!in_proxies_list(target->proxies_list, curproxy)) {
2806 curproxy->next_stkt_ref = target->proxies_list;
2807 target->proxies_list = curproxy;
2808 }
2809 }
2810 }
2811
2812 /* check validity for 'tcp-request' layer 4 rules */
2813 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
2814 err = NULL;
2815 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
2816 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2817 free(err);
2818 cfgerr++;
2819 }
2820 }
2821
2822 /* check validity for 'tcp-request' layer 5 rules */
2823 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
2824 err = NULL;
2825 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
2826 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2827 free(err);
2828 cfgerr++;
2829 }
2830 }
2831
2832 /* check validity for 'tcp-request' layer 6 rules */
2833 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
2834 err = NULL;
2835 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
2836 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2837 free(err);
2838 cfgerr++;
2839 }
2840 }
2841
2842 /* check validity for 'http-request' layer 7 rules */
2843 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
2844 err = NULL;
2845 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
2846 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2847 free(err);
2848 cfgerr++;
2849 }
2850 }
2851
2852 /* check validity for 'http-response' layer 7 rules */
2853 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
2854 err = NULL;
2855 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
2856 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2857 free(err);
2858 cfgerr++;
2859 }
2860 }
2861
2862 if (curproxy->table && curproxy->table->peers.name) {
2863 struct peers *curpeers;
2864
2865 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
2866 if (strcmp(curpeers->id, curproxy->table->peers.name) == 0) {
2867 free((void *)curproxy->table->peers.name);
2868 curproxy->table->peers.p = curpeers;
2869 break;
2870 }
2871 }
2872
2873 if (!curpeers) {
2874 ha_alert("Proxy '%s': unable to find sync peers '%s'.\n",
2875 curproxy->id, curproxy->table->peers.name);
2876 free((void *)curproxy->table->peers.name);
2877 curproxy->table->peers.p = NULL;
2878 cfgerr++;
2879 }
2880 else if (curpeers->state == PR_STSTOPPED) {
2881 /* silently disable this peers section */
2882 curproxy->table->peers.p = NULL;
2883 }
2884 else if (!curpeers->peers_fe) {
2885 ha_alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
2886 curproxy->id, localpeer, curpeers->id);
2887 curproxy->table->peers.p = NULL;
2888 cfgerr++;
2889 }
2890 }
2891
2892
2893 if (curproxy->email_alert.mailers.name) {
2894 struct mailers *curmailers = mailers;
2895
2896 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
2897 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
2898 break;
2899 }
2900 if (!curmailers) {
2901 ha_alert("Proxy '%s': unable to find mailers '%s'.\n",
2902 curproxy->id, curproxy->email_alert.mailers.name);
2903 free_email_alert(curproxy);
2904 cfgerr++;
2905 }
2906 else {
2907 err = NULL;
2908 if (init_email_alert(curmailers, curproxy, &err)) {
2909 ha_alert("Proxy '%s': %s.\n", curproxy->id, err);
2910 free(err);
2911 cfgerr++;
2912 }
2913 }
2914 }
2915
2916 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & STAT_CONVDONE) &&
2917 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
2918 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
2919 ha_alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
2920 "proxy", curproxy->id);
2921 cfgerr++;
2922 goto out_uri_auth_compat;
2923 }
2924
2925 if (curproxy->uri_auth && curproxy->uri_auth->userlist &&
2926 (!(curproxy->uri_auth->flags & STAT_CONVDONE) ||
2927 LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules))) {
2928 const char *uri_auth_compat_req[10];
2929 struct act_rule *rule;
2930 int i = 0;
2931 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
2932 uri_auth_compat_req[i++] = "auth";
2933
2934 if (curproxy->uri_auth->auth_realm) {
2935 uri_auth_compat_req[i++] = "realm";
2936 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
2937 }
2938
2939 uri_auth_compat_req[i++] = "unless";
2940 uri_auth_compat_req[i++] = "{";
2941 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
2942 uri_auth_compat_req[i++] = "}";
2943 uri_auth_compat_req[i++] = "";
2944
2945 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
2946 if (!rule) {
2947 cfgerr++;
2948 break;
2949 }
2950
2951 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
2952
2953 if (curproxy->uri_auth->auth_realm) {
2954 free(curproxy->uri_auth->auth_realm);
2955 curproxy->uri_auth->auth_realm = NULL;
2956 }
2957 curproxy->uri_auth->flags |= STAT_CONVDONE;
2958 }
2959 out_uri_auth_compat:
2960
2961 /* check whether we have a log server that uses RFC5424 log format */
2962 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
2963 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
2964 if (!curproxy->conf.logformat_sd_string) {
2965 /* set the default logformat_sd_string */
2966 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
2967 }
2968 break;
2969 }
2970 }
2971
2972 /* compile the log format */
2973 if (!(curproxy->cap & PR_CAP_FE)) {
2974 if (curproxy->conf.logformat_string != default_http_log_format &&
2975 curproxy->conf.logformat_string != default_tcp_log_format &&
2976 curproxy->conf.logformat_string != clf_http_log_format)
2977 free(curproxy->conf.logformat_string);
2978 curproxy->conf.logformat_string = NULL;
2979 free(curproxy->conf.lfs_file);
2980 curproxy->conf.lfs_file = NULL;
2981 curproxy->conf.lfs_line = 0;
2982
2983 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2984 free(curproxy->conf.logformat_sd_string);
2985 curproxy->conf.logformat_sd_string = NULL;
2986 free(curproxy->conf.lfsd_file);
2987 curproxy->conf.lfsd_file = NULL;
2988 curproxy->conf.lfsd_line = 0;
2989 }
2990
2991 if (curproxy->conf.logformat_string) {
2992 curproxy->conf.args.ctx = ARGC_LOG;
2993 curproxy->conf.args.file = curproxy->conf.lfs_file;
2994 curproxy->conf.args.line = curproxy->conf.lfs_line;
2995 err = NULL;
2996 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
2997 SMP_VAL_FE_LOG_END, &err)) {
2998 ha_alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
2999 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
3000 free(err);
3001 cfgerr++;
3002 }
3003 curproxy->conf.args.file = NULL;
3004 curproxy->conf.args.line = 0;
3005 }
3006
3007 if (curproxy->conf.logformat_sd_string) {
3008 curproxy->conf.args.ctx = ARGC_LOGSD;
3009 curproxy->conf.args.file = curproxy->conf.lfsd_file;
3010 curproxy->conf.args.line = curproxy->conf.lfsd_line;
3011 err = NULL;
3012 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
3013 SMP_VAL_FE_LOG_END, &err)) {
3014 ha_alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
3015 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
3016 free(err);
3017 cfgerr++;
3018 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
3019 ha_alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
3020 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
3021 free(err);
3022 cfgerr++;
3023 }
3024 curproxy->conf.args.file = NULL;
3025 curproxy->conf.args.line = 0;
3026 }
3027
3028 if (curproxy->conf.uniqueid_format_string) {
3029 curproxy->conf.args.ctx = ARGC_UIF;
3030 curproxy->conf.args.file = curproxy->conf.uif_file;
3031 curproxy->conf.args.line = curproxy->conf.uif_line;
3032 err = NULL;
3033 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
3034 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
3035 ha_alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
3036 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
3037 free(err);
3038 cfgerr++;
3039 }
3040 curproxy->conf.args.file = NULL;
3041 curproxy->conf.args.line = 0;
3042 }
3043
3044 /* only now we can check if some args remain unresolved.
3045 * This must be done after the users and groups resolution.
3046 */
3047 cfgerr += smp_resolve_args(curproxy);
3048 if (!cfgerr)
3049 cfgerr += acl_find_targets(curproxy);
3050
3051 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
3052 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
3053 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
3054 (!curproxy->timeout.connect ||
3055 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
3056 ha_warning("config : missing timeouts for %s '%s'.\n"
3057 " | While not properly invalid, you will certainly encounter various problems\n"
3058 " | with such a configuration. To fix this, please ensure that all following\n"
3059 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
3060 proxy_type_str(curproxy), curproxy->id);
3061 err_code |= ERR_WARN;
3062 }
3063
3064 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3065 * We must still support older configurations, so let's find out whether those
3066 * parameters have been set or must be copied from contimeouts.
3067 */
3068 if (!curproxy->timeout.tarpit)
3069 curproxy->timeout.tarpit = curproxy->timeout.connect;
3070 if ((curproxy->cap & PR_CAP_BE) && !curproxy->timeout.queue)
3071 curproxy->timeout.queue = curproxy->timeout.connect;
3072
3073 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
3074 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
3075 curproxy->check_req = malloc(curproxy->check_len);
3076 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
3077 }
3078
3079 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
3080 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
3081 ha_warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
3082 proxy_type_str(curproxy), curproxy->id);
3083 err_code |= ERR_WARN;
3084 }
3085
3086 /* ensure that cookie capture length is not too large */
3087 if (curproxy->capture_len >= global.tune.cookie_len) {
3088 ha_warning("config : truncating capture length to %d bytes for %s '%s'.\n",
3089 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
3090 err_code |= ERR_WARN;
3091 curproxy->capture_len = global.tune.cookie_len - 1;
3092 }
3093
3094 /* The small pools required for the capture lists */
3095 if (curproxy->nb_req_cap) {
3096 curproxy->req_cap_pool = create_pool("ptrcap",
3097 curproxy->nb_req_cap * sizeof(char *),
3098 MEM_F_SHARED);
3099 }
3100
3101 if (curproxy->nb_rsp_cap) {
3102 curproxy->rsp_cap_pool = create_pool("ptrcap",
3103 curproxy->nb_rsp_cap * sizeof(char *),
3104 MEM_F_SHARED);
3105 }
3106
3107 switch (curproxy->load_server_state_from_file) {
3108 case PR_SRV_STATE_FILE_UNSPEC:
3109 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3110 break;
3111 case PR_SRV_STATE_FILE_GLOBAL:
3112 if (!global.server_state_file) {
3113 ha_warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
3114 curproxy->id);
3115 err_code |= ERR_WARN;
3116 }
3117 break;
3118 }
3119
3120 /* first, we will invert the servers list order */
3121 newsrv = NULL;
3122 while (curproxy->srv) {
3123 struct server *next;
3124
3125 next = curproxy->srv->next;
3126 curproxy->srv->next = newsrv;
3127 newsrv = curproxy->srv;
3128 if (!next)
3129 break;
3130 curproxy->srv = next;
3131 }
3132
3133 /* Check that no server name conflicts. This causes trouble in the stats.
3134 * We only emit a warning for the first conflict affecting each server,
3135 * in order to avoid combinatory explosion if all servers have the same
3136 * name. We do that only for servers which do not have an explicit ID,
3137 * because these IDs were made also for distinguishing them and we don't
3138 * want to annoy people who correctly manage them.
3139 */
3140 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
3141 struct server *other_srv;
3142
3143 if (newsrv->puid)
3144 continue;
3145
3146 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
3147 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
3148 ha_alert("parsing [%s:%d] : %s '%s', another server named '%s' was already defined at line %d, please use distinct names.\n",
3149 newsrv->conf.file, newsrv->conf.line,
3150 proxy_type_str(curproxy), curproxy->id,
3151 newsrv->id, other_srv->conf.line);
3152 cfgerr++;
3153 break;
3154 }
3155 }
3156 }
3157
3158 /* assign automatic UIDs to servers which don't have one yet */
3159 next_id = 1;
3160 newsrv = curproxy->srv;
3161 while (newsrv != NULL) {
3162 if (!newsrv->puid) {
3163 /* server ID not set, use automatic numbering with first
3164 * spare entry starting with next_svid.
3165 */
3166 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
3167 newsrv->conf.id.key = newsrv->puid = next_id;
3168 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
3169 newsrv->conf.name.key = newsrv->id;
3170 ebis_insert(&curproxy->conf.used_server_name, &newsrv->conf.name);
3171 }
3172 next_id++;
3173 newsrv = newsrv->next;
3174 }
3175
3176 curproxy->lbprm.wmult = 1; /* default weight multiplier */
3177 curproxy->lbprm.wdiv = 1; /* default weight divider */
3178
3179 /*
3180 * If this server supports a maxconn parameter, it needs a dedicated
3181 * tasks to fill the emptied slots when a connection leaves.
3182 * Also, resolve deferred tracking dependency if needed.
3183 */
3184 newsrv = curproxy->srv;
3185 while (newsrv != NULL) {
3186 if (newsrv->minconn > newsrv->maxconn) {
3187 /* Only 'minconn' was specified, or it was higher than or equal
3188 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3189 * this will avoid further useless expensive computations.
3190 */
3191 newsrv->maxconn = newsrv->minconn;
3192 } else if (newsrv->maxconn && !newsrv->minconn) {
3193 /* minconn was not specified, so we set it to maxconn */
3194 newsrv->minconn = newsrv->maxconn;
3195 }
3196
3197 /* this will also properly set the transport layer for prod and checks */
3198 if (newsrv->use_ssl == 1 || newsrv->check.use_ssl == 1 || (newsrv->proxy->options & PR_O_TCPCHK_SSL)) {
3199 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
3200 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
3201 }
3202
3203 if ((newsrv->flags & SRV_F_FASTOPEN) &&
3204 ((curproxy->retry_type & (PR_RE_DISCONNECTED | PR_RE_TIMEOUT)) !=
3205 (PR_RE_DISCONNECTED | PR_RE_TIMEOUT)))
3206 ha_warning("parsing [%s:%d] : %s '%s': server '%s' has tfo activated, the backend should be configured with at least 'conn-failure', 'empty-response' and 'response-timeout' or we wouldn't be able to retry the connection on failure.\n",
3207 newsrv->conf.file, newsrv->conf.line,
3208 proxy_type_str(curproxy), curproxy->id,
3209 newsrv->id);
3210
3211 if (newsrv->trackit) {
3212 struct proxy *px;
3213 struct server *srv, *loop;
3214 char *pname, *sname;
3215
3216 pname = newsrv->trackit;
3217 sname = strrchr(pname, '/');
3218
3219 if (sname)
3220 *sname++ = '\0';
3221 else {
3222 sname = pname;
3223 pname = NULL;
3224 }
3225
3226 if (pname) {
3227 px = proxy_be_by_name(pname);
3228 if (!px) {
3229 ha_alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3230 proxy_type_str(curproxy), curproxy->id,
3231 newsrv->id, pname);
3232 cfgerr++;
3233 goto next_srv;
3234 }
3235 } else
3236 px = curproxy;
3237
3238 srv = findserver(px, sname);
3239 if (!srv) {
3240 ha_alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3241 proxy_type_str(curproxy), curproxy->id,
3242 newsrv->id, sname);
3243 cfgerr++;
3244 goto next_srv;
3245 }
3246
3247 if (!srv->do_check && !srv->do_agent && !srv->track && !srv->trackit) {
3248 ha_alert("config : %s '%s', server '%s': unable to use %s/%s for "
3249 "tracking as it does not have any check nor agent enabled.\n",
3250 proxy_type_str(curproxy), curproxy->id,
3251 newsrv->id, px->id, srv->id);
3252 cfgerr++;
3253 goto next_srv;
3254 }
3255
3256 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
3257
3258 if (newsrv == srv || loop) {
3259 ha_alert("config : %s '%s', server '%s': unable to track %s/%s as it "
3260 "belongs to a tracking chain looping back to %s/%s.\n",
3261 proxy_type_str(curproxy), curproxy->id,
3262 newsrv->id, px->id, srv->id, px->id,
3263 newsrv == srv ? srv->id : loop->id);
3264 cfgerr++;
3265 goto next_srv;
3266 }
3267
3268 if (curproxy != px &&
3269 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3270 ha_alert("config : %s '%s', server '%s': unable to use %s/%s for"
3271 "tracking: disable-on-404 option inconsistency.\n",
3272 proxy_type_str(curproxy), curproxy->id,
3273 newsrv->id, px->id, srv->id);
3274 cfgerr++;
3275 goto next_srv;
3276 }
3277
3278 newsrv->track = srv;
3279 newsrv->tracknext = srv->trackers;
3280 srv->trackers = newsrv;
3281
3282 free(newsrv->trackit);
3283 newsrv->trackit = NULL;
3284 }
3285
3286 next_srv:
3287 newsrv = newsrv->next;
3288 }
3289
3290 /*
3291 * Try to generate dynamic cookies for servers now.
3292 * It couldn't be done earlier, since at the time we parsed
3293 * the server line, we may not have known yet that we
3294 * should use dynamic cookies, or the secret key may not
3295 * have been provided yet.
3296 */
3297 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
3298 newsrv = curproxy->srv;
3299 while (newsrv != NULL) {
3300 srv_set_dyncookie(newsrv);
3301 newsrv = newsrv->next;
3302 }
3303
3304 }
3305 /* We have to initialize the server lookup mechanism depending
3306 * on what LB algorithm was chosen.
3307 */
3308
3309 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
3310 switch (curproxy->lbprm.algo & BE_LB_KIND) {
3311 case BE_LB_KIND_RR:
3312 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
3313 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
3314 init_server_map(curproxy);
3315 } else if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_RANDOM) {
3316 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
3317 chash_init_server_tree(curproxy);
3318 } else {
3319 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
3320 fwrr_init_server_groups(curproxy);
3321 }
3322 break;
3323
3324 case BE_LB_KIND_CB:
3325 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
3326 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
3327 fwlc_init_server_tree(curproxy);
3328 } else {
3329 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
3330 fas_init_server_tree(curproxy);
3331 }
3332 break;
3333
3334 case BE_LB_KIND_HI:
3335 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
3336 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
3337 chash_init_server_tree(curproxy);
3338 } else {
3339 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
3340 init_server_map(curproxy);
3341 }
3342 break;
3343 }
3344 HA_SPIN_INIT(&curproxy->lbprm.lock);
3345
3346 if (curproxy->options & PR_O_LOGASAP)
3347 curproxy->to_log &= ~LW_BYTES;
3348
3349 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
3350 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
3351 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
3352 ha_warning("config : log format ignored for %s '%s' since it has no log address.\n",
3353 proxy_type_str(curproxy), curproxy->id);
3354 err_code |= ERR_WARN;
3355 }
3356
3357 if (curproxy->mode != PR_MODE_HTTP) {
3358 int optnum;
3359
3360 if (curproxy->uri_auth) {
3361 ha_warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
3362 proxy_type_str(curproxy), curproxy->id);
3363 err_code |= ERR_WARN;
3364 curproxy->uri_auth = NULL;
3365 }
3366
3367 if (curproxy->capture_name) {
3368 ha_warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
3369 proxy_type_str(curproxy), curproxy->id);
3370 err_code |= ERR_WARN;
3371 }
3372
3373 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
3374 ha_warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
3375 proxy_type_str(curproxy), curproxy->id);
3376 err_code |= ERR_WARN;
3377 }
3378
3379 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
3380 ha_warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
3381 proxy_type_str(curproxy), curproxy->id);
3382 err_code |= ERR_WARN;
3383 }
3384
3385 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
3386 ha_warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
3387 proxy_type_str(curproxy), curproxy->id);
3388 err_code |= ERR_WARN;
3389 }
3390
3391 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
3392 ha_warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
3393 "forwardfor", proxy_type_str(curproxy), curproxy->id);
3394 err_code |= ERR_WARN;
3395 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
3396 }
3397
3398 if (curproxy->options & PR_O_ORGTO) {
3399 ha_warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
3400 "originalto", proxy_type_str(curproxy), curproxy->id);
3401 err_code |= ERR_WARN;
3402 curproxy->options &= ~PR_O_ORGTO;
3403 }
3404
3405 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3406 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
3407 (curproxy->cap & cfg_opts[optnum].cap) &&
3408 (curproxy->options & cfg_opts[optnum].val)) {
3409 ha_warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
3410 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
3411 err_code |= ERR_WARN;
3412 curproxy->options &= ~cfg_opts[optnum].val;
3413 }
3414 }
3415
3416 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3417 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
3418 (curproxy->cap & cfg_opts2[optnum].cap) &&
3419 (curproxy->options2 & cfg_opts2[optnum].val)) {
3420 ha_warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
3421 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
3422 err_code |= ERR_WARN;
3423 curproxy->options2 &= ~cfg_opts2[optnum].val;
3424 }
3425 }
3426
3427 #if defined(CONFIG_HAP_TRANSPARENT)
3428 if (curproxy->conn_src.bind_hdr_occ) {
3429 curproxy->conn_src.bind_hdr_occ = 0;
3430 ha_warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
3431 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
3432 err_code |= ERR_WARN;
3433 }
3434 #endif
3435 }
3436
3437 /*
3438 * ensure that we're not cross-dressing a TCP server into HTTP.
3439 */
3440 newsrv = curproxy->srv;
3441 while (newsrv != NULL) {
3442 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
3443 ha_alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3444 proxy_type_str(curproxy), curproxy->id);
3445 cfgerr++;
3446 }
3447
3448 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
3449 ha_warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
3450 proxy_type_str(curproxy), curproxy->id, newsrv->id);
3451 err_code |= ERR_WARN;
3452 }
3453
3454 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
3455 ha_warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
3456 proxy_type_str(curproxy), curproxy->id, newsrv->id);
3457 err_code |= ERR_WARN;
3458 }
3459
3460 #if defined(CONFIG_HAP_TRANSPARENT)
3461 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
3462 newsrv->conn_src.bind_hdr_occ = 0;
3463 ha_warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
3464 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
3465 err_code |= ERR_WARN;
3466 }
3467 #endif
3468
3469 if ((curproxy->mode != PR_MODE_HTTP) && (curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR)
3470 curproxy->options &= ~PR_O_REUSE_MASK;
3471
3472 newsrv = newsrv->next;
3473 }
3474
3475 /* check if we have a frontend with "tcp-request content" looking at L7
3476 * with no inspect-delay
3477 */
3478 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
3479 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
3480 if (arule->action == ACT_TCP_CAPTURE &&
3481 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
3482 break;
3483 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
3484 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
3485 break;
3486 }
3487
3488 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
3489 ha_warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
3490 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
3491 " This means that these rules will randomly find their contents. This can be fixed by"
3492 " setting the tcp-request inspect-delay.\n",
3493 proxy_type_str(curproxy), curproxy->id);
3494 err_code |= ERR_WARN;
3495 }
3496 }
3497
3498 /* Check filter configuration, if any */
3499 cfgerr += flt_check(curproxy);
3500
3501 if (curproxy->cap & PR_CAP_FE) {
3502 if (!curproxy->accept)
3503 curproxy->accept = frontend_accept;
3504
3505 if (curproxy->tcp_req.inspect_delay ||
3506 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
3507 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
3508
3509 if (curproxy->mode == PR_MODE_HTTP) {
3510 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
3511 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
3512 }
3513
3514 if (curproxy->mode == PR_MODE_CLI) {
3515 curproxy->fe_req_ana |= AN_REQ_WAIT_CLI;
3516 curproxy->fe_rsp_ana |= AN_RES_WAIT_CLI;
3517 }
3518
3519 /* both TCP and HTTP must check switching rules */
3520 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
3521
3522 /* Add filters analyzers if needed */
3523 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
3524 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
3525 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
3526 if (curproxy->mode == PR_MODE_HTTP) {
3527 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
3528 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
3529 }
3530 }
3531 }
3532
3533 if (curproxy->cap & PR_CAP_BE) {
3534 if (curproxy->tcp_req.inspect_delay ||
3535 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
3536 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
3537
3538 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
3539 curproxy->be_rsp_ana |= AN_RES_INSPECT;
3540
3541 if (curproxy->mode == PR_MODE_HTTP) {
3542 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
3543 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
3544 }
3545
3546 /* If the backend does requires RDP cookie persistence, we have to
3547 * enable the corresponding analyser.
3548 */
3549 if (curproxy->options2 & PR_O2_RDPC_PRST)
3550 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
3551
3552 /* Add filters analyzers if needed */
3553 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
3554 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
3555 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
3556 if (curproxy->mode == PR_MODE_HTTP) {
3557 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
3558 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
3559 }
3560 }
3561 }
3562
3563 /* Check the mux protocols, if any, for each listener and server
3564 * attached to the current proxy */
3565 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
3566 int mode = (1 << (curproxy->mode == PR_MODE_HTTP));
3567 const struct mux_proto_list *mux_ent;
3568
3569 if (!bind_conf->mux_proto)
3570 continue;
3571
3572 /* it is possible that an incorrect mux was referenced
3573 * due to the proxy's mode not being taken into account
3574 * on first pass. Let's adjust it now.
3575 */
3576 mux_ent = conn_get_best_mux_entry(bind_conf->mux_proto->token, PROTO_SIDE_FE, mode);
3577
3578 if (!mux_ent || !isteq(mux_ent->token, bind_conf->mux_proto->token)) {
3579 ha_alert("config : %s '%s' : MUX protocol '%.*s' is not usable for 'bind %s' at [%s:%d].\n",
3580 proxy_type_str(curproxy), curproxy->id,
3581 (int)bind_conf->mux_proto->token.len,
3582 bind_conf->mux_proto->token.ptr,
3583 bind_conf->arg, bind_conf->file, bind_conf->line);
3584 cfgerr++;
3585 }
3586
3587 /* update the mux */
3588 bind_conf->mux_proto = mux_ent;
3589 }
3590 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
3591 int mode = (1 << (curproxy->mode == PR_MODE_HTTP));
3592 const struct mux_proto_list *mux_ent;
3593
3594 if (!newsrv->mux_proto)
3595 continue;
3596
3597 /* it is possible that an incorrect mux was referenced
3598 * due to the proxy's mode not being taken into account
3599 * on first pass. Let's adjust it now.
3600 */
3601 mux_ent = conn_get_best_mux_entry(newsrv->mux_proto->token, PROTO_SIDE_BE, mode);
3602
3603 if (!mux_ent || !isteq(mux_ent->token, newsrv->mux_proto->token)) {
3604 ha_alert("config : %s '%s' : MUX protocol '%.*s' is not usable for server '%s' at [%s:%d].\n",
3605 proxy_type_str(curproxy), curproxy->id,
3606 (int)newsrv->mux_proto->token.len,
3607 newsrv->mux_proto->token.ptr,
3608 newsrv->id, newsrv->conf.file, newsrv->conf.line);
3609 cfgerr++;
3610 }
3611
3612 /* update the mux */
3613 newsrv->mux_proto = mux_ent;
3614 }
3615
3616 /* initialize idle conns lists */
3617 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
3618 int i;
3619
3620 newsrv->priv_conns = calloc(global.nbthread, sizeof(*newsrv->priv_conns));
3621 newsrv->idle_conns = calloc(global.nbthread, sizeof(*newsrv->idle_conns));
3622 newsrv->safe_conns = calloc(global.nbthread, sizeof(*newsrv->safe_conns));
3623
3624 if (!newsrv->priv_conns || !newsrv->idle_conns || !newsrv->safe_conns) {
3625 free(newsrv->safe_conns); newsrv->safe_conns = NULL;
3626 free(newsrv->idle_conns); newsrv->idle_conns = NULL;
3627 free(newsrv->priv_conns); newsrv->priv_conns = NULL;
3628 ha_alert("parsing [%s:%d] : failed to allocate idle connections for server '%s'.\n",
3629 newsrv->conf.file, newsrv->conf.line, newsrv->id);
3630 cfgerr++;
3631 continue;
3632 }
3633
3634 for (i = 0; i < global.nbthread; i++) {
3635 LIST_INIT(&newsrv->priv_conns[i]);
3636 LIST_INIT(&newsrv->idle_conns[i]);
3637 LIST_INIT(&newsrv->safe_conns[i]);
3638 }
3639
3640 if (newsrv->max_idle_conns != 0) {
3641 if (idle_conn_task == NULL) {
3642 idle_conn_task = task_new(MAX_THREADS_MASK);
3643 if (!idle_conn_task)
3644 goto err;
3645 idle_conn_task->process = srv_cleanup_idle_connections;
3646 idle_conn_task->context = NULL;
3647 for (i = 0; i < global.nbthread; i++) {
3648 idle_conn_cleanup[i] = task_new(1UL << i);
3649 if (!idle_conn_cleanup[i])
3650 goto err;
3651 idle_conn_cleanup[i]->process = srv_cleanup_toremove_connections;
3652 idle_conn_cleanup[i]->context = NULL;
3653 HA_SPIN_INIT(&toremove_lock[i]);
3654 MT_LIST_INIT(&toremove_connections[i]);
3655 }
3656 }
3657 newsrv->idle_orphan_conns = calloc((unsigned short)global.nbthread, sizeof(*newsrv->idle_orphan_conns));
3658 if (!newsrv->idle_orphan_conns)
3659 goto err;
3660 for (i = 0; i < global.nbthread; i++)
3661 MT_LIST_INIT(&newsrv->idle_orphan_conns[i]);
3662 newsrv->curr_idle_thr = calloc(global.nbthread, sizeof(*newsrv->curr_idle_thr));
3663 if (!newsrv->curr_idle_thr)
3664 goto err;
3665 continue;
3666 err:
3667 ha_alert("parsing [%s:%d] : failed to allocate idle connection tasks for server '%s'.\n",
3668 newsrv->conf.file, newsrv->conf.line, newsrv->id);
3669 cfgerr++;
3670 continue;
3671 }
3672 }
3673 }
3674
3675 /***********************************************************/
3676 /* At this point, target names have already been resolved. */
3677 /***********************************************************/
3678
3679 /* Check multi-process mode compatibility */
3680
3681 if (global.nbproc > 1 && global.stats_fe) {
3682 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
3683 unsigned long mask;
3684
3685 mask = proc_mask(global.stats_fe->bind_proc) && all_proc_mask;
3686 mask &= proc_mask(bind_conf->bind_proc);
3687
3688 /* stop here if more than one process is used */
3689 if (atleast2(mask))
3690 break;
3691 }
3692 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
3693 ha_warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
3694 }
3695 }
3696
3697 /* Make each frontend inherit bind-process from its listeners when not specified. */
3698 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
3699 if (curproxy->bind_proc)
3700 continue;
3701
3702 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
3703 unsigned long mask;
3704
3705 mask = proc_mask(bind_conf->bind_proc);
3706 curproxy->bind_proc |= mask;
3707 }
3708 curproxy->bind_proc = proc_mask(curproxy->bind_proc);
3709 }
3710
3711 if (global.stats_fe) {
3712 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
3713 unsigned long mask;
3714
3715 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
3716 global.stats_fe->bind_proc |= mask;
3717 }
3718 global.stats_fe->bind_proc = proc_mask(global.stats_fe->bind_proc);
3719 }
3720
3721 /* propagate bindings from frontends to backends. Don't do it if there
3722 * are any fatal errors as we must not call it with unresolved proxies.
3723 */
3724 if (!cfgerr) {
3725 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
3726 if (curproxy->cap & PR_CAP_FE)
3727 propagate_processes(curproxy, NULL);
3728 }
3729 }
3730
3731 /* Bind each unbound backend to all processes when not specified. */
3732 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next)
3733 curproxy->bind_proc = proc_mask(curproxy->bind_proc);
3734
3735 /*******************************************************/
3736 /* At this step, all proxies have a non-null bind_proc */
3737 /*******************************************************/
3738
3739 /* perform the final checks before creating tasks */
3740
3741 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
3742 struct listener *listener;
3743 unsigned int next_id;
3744
3745 /* Configure SSL for each bind line.
3746 * Note: if configuration fails at some point, the ->ctx member
3747 * remains NULL so that listeners can later detach.
3748 */
3749 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
3750 if (bind_conf->xprt->prepare_bind_conf &&
3751 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
3752 cfgerr++;
3753 }
3754
3755 /* adjust this proxy's listeners */
3756 next_id = 1;
3757 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
3758 int nbproc;
3759
3760 nbproc = my_popcountl(curproxy->bind_proc &
3761 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
3762 all_proc_mask);
3763
3764 if (!nbproc) /* no intersection between listener and frontend */
3765 nbproc = 1;
3766
3767 if (!listener->luid) {
3768 /* listener ID not set, use automatic numbering with first
3769 * spare entry starting with next_luid.
3770 */
3771 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
3772 listener->conf.id.key = listener->luid = next_id;
3773 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
3774 }
3775 next_id++;
3776
3777 /* enable separate counters */
3778 if (curproxy->options2 & PR_O2_SOCKSTAT) {
3779 listener->counters = calloc(1, sizeof(*listener->counters));
3780 if (!listener->name)
3781 memprintf(&listener->name, "sock-%d", listener->luid);
3782 }
3783
3784 if (curproxy->options & PR_O_TCP_NOLING)
3785 listener->options |= LI_O_NOLINGER;
3786 if (!listener->maxaccept)
3787 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
3788
3789 /* we want to have an optimal behaviour on single process mode to
3790 * maximize the work at once, but in multi-process we want to keep
3791 * some fairness between processes, so we target half of the max
3792 * number of events to be balanced over all the processes the proxy
3793 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
3794 * used to disable the limit.
3795 */
3796 if (listener->maxaccept > 0 && nbproc > 1) {
3797 listener->maxaccept = (listener->maxaccept + 1) / 2;
3798 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
3799 }
3800
3801 listener->accept = session_accept_fd;
3802 listener->analysers |= curproxy->fe_req_ana;
3803 listener->default_target = curproxy->default_target;
3804
3805 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
3806 listener->options |= LI_O_TCP_L4_RULES;
3807
3808 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
3809 listener->options |= LI_O_TCP_L5_RULES;
3810
3811 if (curproxy->mon_mask.s_addr)
3812 listener->options |= LI_O_CHK_MONNET;
3813
3814 /* smart accept mode is automatic in HTTP mode */
3815 if ((curproxy->options2 & PR_O2_SMARTACC) ||
3816 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
3817 !(curproxy->no_options2 & PR_O2_SMARTACC)))
3818 listener->options |= LI_O_NOQUICKACK;
3819 }
3820
3821 /* Release unused SSL configs */
3822 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
3823 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
3824 bind_conf->xprt->destroy_bind_conf(bind_conf);
3825 }
3826
3827 if (atleast2(curproxy->bind_proc & all_proc_mask)) {
3828 if (curproxy->uri_auth) {
3829 int count, maxproc = 0;
3830
3831 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
3832 count = my_popcountl(bind_conf->bind_proc);
3833 if (count > maxproc)
3834 maxproc = count;
3835 }
3836 /* backends have 0, frontends have 1 or more */
3837 if (maxproc != 1)
3838 ha_warning("Proxy '%s': in multi-process mode, stats will be"
3839 " limited to process assigned to the current request.\n",
3840 curproxy->id);
3841
3842 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
3843 ha_warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
3844 curproxy->id);
3845 }
3846 }
3847 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
3848 ha_warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
3849 curproxy->id);
3850 }
3851 }
3852
3853 /* create the task associated with the proxy */
3854 curproxy->task = task_new(MAX_THREADS_MASK);
3855 if (curproxy->task) {
3856 curproxy->task->context = curproxy;
3857 curproxy->task->process = manage_proxy;
3858 } else {
3859 ha_alert("Proxy '%s': no more memory when trying to allocate the management task\n",
3860 curproxy->id);
3861 cfgerr++;
3862 }
3863 }
3864
3865 /*
3866 * Recount currently required checks.
3867 */
3868
3869 for (curproxy=proxies_list; curproxy; curproxy=curproxy->next) {
3870 int optnum;
3871
3872 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3873 if (curproxy->options & cfg_opts[optnum].val)
3874 global.last_checks |= cfg_opts[optnum].checks;
3875
3876 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3877 if (curproxy->options2 & cfg_opts2[optnum].val)
3878 global.last_checks |= cfg_opts2[optnum].checks;
3879 }
3880
3881 /* compute the required process bindings for the peers */
3882 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next)
3883 if (curproxy->table && curproxy->table->peers.p)
3884 curproxy->table->peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
3885
3886 /* compute the required process bindings for the peers from <stktables_list>
3887 * for all the stick-tables, the ones coming with "peers" sections included.
3888 */
3889 for (t = stktables_list; t; t = t->next) {
3890 struct proxy *p;
3891
3892 for (p = t->proxies_list; p; p = p->next_stkt_ref) {
3893 if (t->peers.p && t->peers.p->peers_fe) {
3894 t->peers.p->peers_fe->bind_proc |= p->bind_proc;
3895 }
3896 }
3897 }
3898
3899 if (cfg_peers) {
3900 struct peers *curpeers = cfg_peers, **last;
3901 struct peer *p, *pb;
3902
3903 /* In the case the peers frontend was not initialized by a
3904 stick-table used in the configuration, set its bind_proc
3905 by default to the first process. */
3906 while (curpeers) {
3907 if (curpeers->peers_fe) {
3908 if (curpeers->peers_fe->bind_proc == 0)
3909 curpeers->peers_fe->bind_proc = 1;
3910 }
3911 curpeers = curpeers->next;
3912 }
3913
3914 curpeers = cfg_peers;
3915 /* Remove all peers sections which don't have a valid listener,
3916 * which are not used by any table, or which are bound to more
3917 * than one process.
3918 */
3919 last = &cfg_peers;
3920 while (*last) {
3921 struct stktable *t;
3922 curpeers = *last;
3923
3924 if (curpeers->state == PR_STSTOPPED) {
3925 /* the "disabled" keyword was present */
3926 if (curpeers->peers_fe)
3927 stop_proxy(curpeers->peers_fe);
3928 curpeers->peers_fe = NULL;
3929 }
3930 else if (!curpeers->peers_fe || !curpeers->peers_fe->id) {
3931 ha_warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
3932 curpeers->id, localpeer);
3933 if (curpeers->peers_fe)
3934 stop_proxy(curpeers->peers_fe);
3935 curpeers->peers_fe = NULL;
3936 }
3937 else if (atleast2(curpeers->peers_fe->bind_proc)) {
3938 /* either it's totally stopped or too much used */
3939 if (curpeers->peers_fe->bind_proc) {
3940 ha_alert("Peers section '%s': peers referenced by sections "
3941 "running in different processes (%d different ones). "
3942 "Check global.nbproc and all tables' bind-process "
3943 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
3944 cfgerr++;
3945 }
3946 stop_proxy(curpeers->peers_fe);
3947 curpeers->peers_fe = NULL;
3948 }
3949 else {
3950 /* Initializes the transport layer of the server part of all the peers belonging to
3951 * <curpeers> section if required.
3952 * Note that ->srv is used by the local peer of a new process to connect to the local peer
3953 * of an old process.
3954 */
3955 p = curpeers->remote;
3956 while (p) {
3957 if (p->srv) {
3958 if (p->srv->use_ssl == 1 && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
3959 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv);
3960 }
3961 p = p->next;
3962 }
3963 /* Configure the SSL bindings of the local peer if required. */
3964 if (!LIST_ISEMPTY(&curpeers->peers_fe->conf.bind)) {
3965 struct list *l;
3966 struct bind_conf *bind_conf;
3967
3968 l = &curpeers->peers_fe->conf.bind;
3969 bind_conf = LIST_ELEM(l->n, typeof(bind_conf), by_fe);
3970 if (bind_conf->xprt->prepare_bind_conf &&
3971 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
3972 cfgerr++;
3973 }
3974 if (!peers_init_sync(curpeers) || !peers_alloc_dcache(curpeers)) {
3975 ha_alert("Peers section '%s': out of memory, giving up on peers.\n",
3976 curpeers->id);
3977 cfgerr++;
3978 break;
3979 }
3980 last = &curpeers->next;
3981 continue;
3982 }
3983
3984 /* clean what has been detected above */
3985 p = curpeers->remote;
3986 while (p) {
3987 pb = p->next;
3988 free(p->id);
3989 free(p);
3990 p = pb;
3991 }
3992
3993 /* Destroy and unlink this curpeers section.
3994 * Note: curpeers is backed up into *last.
3995 */
3996 free(curpeers->id);
3997 curpeers = curpeers->next;
3998 /* Reset any refereance to this peers section in the list of stick-tables */
3999 for (t = stktables_list; t; t = t->next) {
4000 if (t->peers.p && t->peers.p == *last)
4001 t->peers.p = NULL;
4002 }
4003 free(*last);
4004 *last = curpeers;
4005 }
4006 }
4007
4008 for (t = stktables_list; t; t = t->next) {
4009 if (t->proxy)
4010 continue;
4011 if (!stktable_init(t)) {
4012 ha_alert("Proxy '%s': failed to initialize stick-table.\n", t->id);
4013 cfgerr++;
4014 }
4015 }
4016
4017 /* initialize stick-tables on backend capable proxies. This must not
4018 * be done earlier because the data size may be discovered while parsing
4019 * other proxies.
4020 */
4021 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
4022 if (curproxy->state == PR_STSTOPPED || !curproxy->table)
4023 continue;
4024
4025 if (!stktable_init(curproxy->table)) {
4026 ha_alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
4027 cfgerr++;
4028 }
4029 }
4030
4031 if (mailers) {
4032 struct mailers *curmailers = mailers, **last;
4033 struct mailer *m, *mb;
4034
4035 /* Remove all mailers sections which don't have a valid listener.
4036 * This can happen when a mailers section is never referenced.
4037 */
4038 last = &mailers;
4039 while (*last) {
4040 curmailers = *last;
4041 if (curmailers->users) {
4042 last = &curmailers->next;
4043 continue;
4044 }
4045
4046 ha_warning("Removing incomplete section 'mailers %s'.\n",
4047 curmailers->id);
4048
4049 m = curmailers->mailer_list;
4050 while (m) {
4051 mb = m->next;
4052 free(m->id);
4053 free(m);
4054 m = mb;
4055 }
4056
4057 /* Destroy and unlink this curmailers section.
4058 * Note: curmailers is backed up into *last.
4059 */
4060 free(curmailers->id);
4061 curmailers = curmailers->next;
4062 free(*last);
4063 *last = curmailers;
4064 }
4065 }
4066
4067 /* Update server_state_file_name to backend name if backend is supposed to use
4068 * a server-state file locally defined and none has been provided */
4069 for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
4070 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
4071 curproxy->server_state_file_name == NULL)
4072 curproxy->server_state_file_name = strdup(curproxy->id);
4073 }
4074
4075 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
4076 if (LIST_ISEMPTY(&curr_resolvers->nameservers)) {
4077 ha_warning("config : resolvers '%s' [%s:%d] has no nameservers configured!\n",
4078 curr_resolvers->id, curr_resolvers->conf.file,
4079 curr_resolvers->conf.line);
4080 err_code |= ERR_WARN;
4081 }
4082 }
4083
4084 list_for_each_entry(postparser, &postparsers, list) {
4085 if (postparser->func)
4086 cfgerr += postparser->func();
4087 }
4088
4089 if (cfgerr > 0)
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 out:
4092 return err_code;
4093 }
4094
4095 /*
4096 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4097 * parsing sessions.
4098 */
cfg_register_keywords(struct cfg_kw_list * kwl)4099 void cfg_register_keywords(struct cfg_kw_list *kwl)
4100 {
4101 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4102 }
4103
4104 /*
4105 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4106 */
cfg_unregister_keywords(struct cfg_kw_list * kwl)4107 void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4108 {
4109 LIST_DEL(&kwl->list);
4110 LIST_INIT(&kwl->list);
4111 }
4112
4113 /* this function register new section in the haproxy configuration file.
4114 * <section_name> is the name of this new section and <section_parser>
4115 * is the called parser. If two section declaration have the same name,
4116 * only the first declared is used.
4117 */
cfg_register_section(char * section_name,int (* section_parser)(const char *,int,char **,int),int (* post_section_parser)())4118 int cfg_register_section(char *section_name,
4119 int (*section_parser)(const char *, int, char **, int),
4120 int (*post_section_parser)())
4121 {
4122 struct cfg_section *cs;
4123
4124 list_for_each_entry(cs, §ions, list) {
4125 if (strcmp(cs->section_name, section_name) == 0) {
4126 ha_alert("register section '%s': already registered.\n", section_name);
4127 return 0;
4128 }
4129 }
4130
4131 cs = calloc(1, sizeof(*cs));
4132 if (!cs) {
4133 ha_alert("register section '%s': out of memory.\n", section_name);
4134 return 0;
4135 }
4136
4137 cs->section_name = section_name;
4138 cs->section_parser = section_parser;
4139 cs->post_section_parser = post_section_parser;
4140
4141 LIST_ADDQ(§ions, &cs->list);
4142
4143 return 1;
4144 }
4145
4146 /* this function register a new function which will be called once the haproxy
4147 * configuration file has been parsed. It's useful to check dependencies
4148 * between sections or to resolve items once everything is parsed.
4149 */
cfg_register_postparser(char * name,int (* func)())4150 int cfg_register_postparser(char *name, int (*func)())
4151 {
4152 struct cfg_postparser *cp;
4153
4154 cp = calloc(1, sizeof(*cp));
4155 if (!cp) {
4156 ha_alert("register postparser '%s': out of memory.\n", name);
4157 return 0;
4158 }
4159 cp->name = name;
4160 cp->func = func;
4161
4162 LIST_ADDQ(&postparsers, &cp->list);
4163
4164 return 1;
4165 }
4166
4167 /*
4168 * free all config section entries
4169 */
cfg_unregister_sections(void)4170 void cfg_unregister_sections(void)
4171 {
4172 struct cfg_section *cs, *ics;
4173
4174 list_for_each_entry_safe(cs, ics, §ions, list) {
4175 LIST_DEL(&cs->list);
4176 free(cs);
4177 }
4178 }
4179
cfg_backup_sections(struct list * backup_sections)4180 void cfg_backup_sections(struct list *backup_sections)
4181 {
4182 struct cfg_section *cs, *ics;
4183
4184 list_for_each_entry_safe(cs, ics, §ions, list) {
4185 LIST_DEL(&cs->list);
4186 LIST_ADDQ(backup_sections, &cs->list);
4187 }
4188 }
4189
cfg_restore_sections(struct list * backup_sections)4190 void cfg_restore_sections(struct list *backup_sections)
4191 {
4192 struct cfg_section *cs, *ics;
4193
4194 list_for_each_entry_safe(cs, ics, backup_sections, list) {
4195 LIST_DEL(&cs->list);
4196 LIST_ADDQ(§ions, &cs->list);
4197 }
4198 }
4199
4200 /* these are the config sections handled by default */
4201 REGISTER_CONFIG_SECTION("listen", cfg_parse_listen, NULL);
4202 REGISTER_CONFIG_SECTION("frontend", cfg_parse_listen, NULL);
4203 REGISTER_CONFIG_SECTION("backend", cfg_parse_listen, NULL);
4204 REGISTER_CONFIG_SECTION("defaults", cfg_parse_listen, NULL);
4205 REGISTER_CONFIG_SECTION("global", cfg_parse_global, NULL);
4206 REGISTER_CONFIG_SECTION("userlist", cfg_parse_users, NULL);
4207 REGISTER_CONFIG_SECTION("peers", cfg_parse_peers, NULL);
4208 REGISTER_CONFIG_SECTION("mailers", cfg_parse_mailers, NULL);
4209 REGISTER_CONFIG_SECTION("namespace_list", cfg_parse_netns, NULL);
4210 REGISTER_CONFIG_SECTION("resolvers", cfg_parse_resolvers, NULL);
4211
4212 /*
4213 * Local variables:
4214 * c-indent-level: 8
4215 * c-basic-offset: 8
4216 * End:
4217 */
4218