The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
cf_parse.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 0111d7f3bf061c060e15cc072b0cbe4009b60252 $
19 * @file cf_parse.c
20 * @brief Convert internal format configuration values into native C types.
21 *
22 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 * @copyright 2000,2006 The FreeRADIUS server project
24 * @copyright 2000 Alan DeKok (aland@freeradius.org)
25 */
26RCSID("$Id: 0111d7f3bf061c060e15cc072b0cbe4009b60252 $")
27
28#include <string.h>
29#include <sys/errno.h>
30#include <sys/fcntl.h>
31
32#include <freeradius-devel/server/cf_file.h>
33#include <freeradius-devel/server/cf_parse.h>
34#include <freeradius-devel/server/cf_priv.h>
35#include <freeradius-devel/server/log.h>
36#include <freeradius-devel/server/tmpl.h>
37#include <freeradius-devel/server/virtual_servers.h>
38#include <freeradius-devel/server/main_config.h>
39#include <freeradius-devel/util/debug.h>
40#include <freeradius-devel/util/inet.h>
41#include <freeradius-devel/util/misc.h>
42#include <freeradius-devel/util/perm.h>
43
45static char const parse_spaces[] = " ";
46
47#define PAIR_SPACE(_cs) ((_cs->depth + 1) * 2)
48#define SECTION_SPACE(_cs) (_cs->depth * 2)
49
50void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
51{
52 char const *value;
53 char *tmp = NULL;
54 char const *quote = "";
55 bool secret = (rule && (rule->flags & CONF_FLAG_SECRET));
57
58 if (cp->printed) return;
59
60 /*
61 * tmpls are special, they just need to get printed as string
62 */
63 if (!rule || (rule->flags & CONF_FLAG_TMPL)) {
65 } else {
66 type = rule->type;
67 }
68
69 if (secret && (fr_debug_lvl < L_DBG_LVL_3)) {
70 cf_log_debug(cs, "%.*s%s = <<< secret >>>", PAIR_SPACE(cs), parse_spaces, cp->attr);
71 return;
72 }
73
74 /*
75 * Print the strings with the correct quotation character and escaping.
76 */
78 value = tmp = fr_asprint(NULL, cp->value, talloc_strlen(cp->value), fr_token_quote[cp->rhs_quote]);
79
80 } else {
81 value = cf_pair_value(cp);
82 }
83
85 switch (cf_pair_value_quote(cp)) {
86 default:
87 break;
88
90 quote = "\"";
91 break;
92
94 quote = "'";
95 break;
96
98 quote = "`";
99 break;
100
102 quote = "/";
103 break;
104 }
105 }
106
107 cf_log_debug(cs, "%.*s%s = %s%s%s", PAIR_SPACE(cs), parse_spaces, cp->attr, quote, value, quote);
108
109 talloc_free(tmp);
110
111 cp->printed = true;
112}
113
114/** Parses a #CONF_PAIR into a boxed value
115 *
116 * @copybrief cf_pair_value
117 * @see cf_pair_value
118 *
119 * @param[in] ctx to allocate any dynamic buffers in.
120 * @param[out] out Where to write the parsed value.
121 * @param[in] cp to parse.
122 * @param[in] rule to parse to. May contain flags.
123 * @return
124 * - 0 on success.
125 * - -1 on failure.
126 */
127int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
128{
129 if (fr_value_box_from_str(ctx, out, rule->type, NULL, cp->value, talloc_strlen(cp->value), NULL) < 0) {
130 cf_log_perr(cp, "Invalid value \"%s\" for config item %s (data type %s)",
131 cp->value, cp->attr, fr_type_to_str(rule->type));
132
133 return -1;
134 }
135
136 /*
137 * Strings can be file paths...
138 */
139 if (fr_type_is_string(rule->type)) {
140 if (fr_rule_file_socket(rule)) {
141 /*
142 * Attempt to actually connect to the socket.
143 * There's no real standard behaviour across
144 * operating systems for this.
145 *
146 * This also implies fr_rule_file_exists.
147 */
148 if (fr_rule_file_readable(rule) || fr_rule_file_writable(rule)) {
150 cf_log_perr(cp, "File check failed");
151 return -1;
152 }
153 /*
154 * Otherwise just passively check if the socket
155 * exists.
156 */
157 } else if (fr_rule_file_exists(rule)) {
159 cf_log_perr(cp, "File check failed");
160 return -1;
161 }
162 /*
163 * ...and if there's no existence requirement
164 * just check that it's a unix socket.
165 */
166 } else {
168 default:
169 /* ok */
170 break;
171
173 cf_log_perr(cp, "File check failed");
174 return -1;
175 }
176 }
177 }
178 /*
179 * If there's out AND it's an input file, check
180 * that we can read it. This check allows errors
181 * to be caught as early as possible, during
182 * server startup.
183 */
184 else if (fr_rule_file_readable(rule) && (cf_file_check(cp, true) < 0)) {
185 error:
187 return -1;
188 }
189 else if (fr_rule_file_exists(rule) && (cf_file_check(cp, false) < 0)) goto error;
190 }
191
193
194 return 0;
195}
196
197/** Parses a #CONF_PAIR into a C data type
198 *
199 * @copybrief cf_pair_value
200 * @see cf_pair_value
201 *
202 * @param[in] ctx to allocate any dynamic buffers in.
203 * @param[out] out Where to write the parsed value.
204 * @param[in] base address of the structure out points into.
205 * May be NULL in the case of manual parsing.
206 * @param[in] ci to parse.
207 * @param[in] rule to parse to. May contain flags.
208 * @return
209 * - 0 on success.
210 * - -1 on failure.
211 */
212int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
213{
214 int ret = 0;
215 bool cant_be_empty, tmpl;
216
217 fr_slen_t slen;
218
219 CONF_PAIR *cp = cf_item_to_pair(ci);
220
221 cant_be_empty = fr_rule_not_empty(rule);
222 tmpl = fr_rule_is_tmpl(rule);
223
224 fr_assert(cp);
225 fr_assert(!fr_rule_is_attribute(rule) || tmpl); /* Attribute flag only valid for templates */
226
227 if (fr_rule_required(rule)) cant_be_empty = true; /* May want to review this in the future... */
228
229 /*
230 * Everything except templates must have a base type.
231 */
232 if (!rule->type && !tmpl) {
233 cf_log_err(cp, "Configuration pair \"%s\" must have a data type", cp->attr);
234 return -1;
235 }
236
237 /*
238 * Catch crazy errors.
239 */
240 if (!cp->value) {
241 cf_log_err(cp, "Configuration pair \"%s\" must have a value", cp->attr);
242 return -1;
243 }
244
245 /*
246 * Check for zero length strings
247 */
248 if ((cp->value[0] == '\0') && cant_be_empty) {
249 cf_log_err(cp, "Configuration pair \"%s\" must not be empty (zero length)", cp->attr);
250 if (!fr_rule_required(rule)) cf_log_err(cp, "Comment item to silence this message");
251 error:
252 ret = -1;
253 return ret;
254 }
255
256 if (tmpl) {
257 tmpl_t *vpt;
258 static tmpl_rules_t rules = {
259 .attr = {
260 .allow_unknown = true,
261 .allow_unresolved = true,
262 .allow_foreign = true,
263 },
264 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
265 };
266 fr_sbuff_t sbuff = FR_SBUFF_IN(cp->value, strlen(cp->value));
267
269
270 /*
271 * Bare words are magical sometimes.
272 */
273 if (cp->rhs_quote == T_BARE_WORD) {
274 /*
275 * Attributes are parsed as attributes.
276 */
277 if (fr_rule_is_attribute(rule)) {
278 slen = tmpl_afrom_attr_substr(cp, NULL, &vpt, &sbuff, NULL, &rules);
279 if (slen < 0) goto tmpl_error;
280
281 fr_assert(vpt);
282
283 *(tmpl_t **)out = vpt;
284 goto finish;
285 }
286
287 /*
288 * @todo - otherwise bare words are NOT parsed as attributes, they're parsed as
289 * bare words, ala v3.
290 */
291
292 } else if (fr_rule_is_attribute(rule)) {
293 cf_log_err(cp, "Unexpected quoted string. An attribute name is required here.");
294 goto error;
295 }
296
297 slen = tmpl_afrom_substr(cp, &vpt, &sbuff, cp->rhs_quote,
299 &rules);
300 if (slen < 0) {
301 tmpl_error:
302 cf_canonicalize_error(cp, slen, fr_strerror(), cp->value);
303 goto error;
304 }
305 fr_assert(vpt);
306
307 /*
308 * The caller told us what data type was expected. If we do have data, then try to cast
309 * it to the requested type.
310 */
311 if ((rule->type != FR_TYPE_VOID) && tmpl_contains_data(vpt)) {
312 slen = 0; // for errors
313
315 tmpl_cast_set(vpt, rule->type);
316
317 if (tmpl_resolve(vpt, NULL) < 0) goto tmpl_error;
318
319 } else if (rule->type != tmpl_value_type(vpt)) {
321
322 if (tmpl_cast_in_place(vpt, rule->type, NULL) < 0) goto tmpl_error;
323 }
324 }
325
326 *(tmpl_t **)out = vpt;
327 goto finish;
328 }
329
330 /*
331 * Parse as a boxed value out of sheer laziness...
332 *
333 * Then we get all the internal types for free, and only need to add
334 * one set of printing and parsing functions for new types...
335 */
336 {
338
339 if (cf_pair_to_value_box(ctx, &vb, cf_item_to_pair(ci), rule) < 0) goto error;
340
341 if (fr_value_box_memcpy_out(out, &vb) < 0) {
342 cf_log_perr(cp, "Failed unboxing parsed configuration item value");
344 goto error;
345 }
346 }
347
348finish:
349
350 return ret;
351}
352
353/** Allocate a pair using the dflt value and quotation
354 *
355 * The pair created by this function should fed to #cf_pair_parse for parsing.
356 *
357 * @param[out] out Where to write the CONF_PAIR we created with the default value.
358 * @param[in] parent being populated.
359 * @param[in] cs to parent the CONF_PAIR from.
360 * @param[in] rule to use to create the default.
361 * @return
362 * - 0 on success.
363 * - -1 on failure.
364 */
365static int cf_pair_default(CONF_PAIR **out, void *parent, CONF_SECTION *cs, conf_parser_t const *rule)
366
367{
368 int lineno = 0;
369 char const *expanded;
370 CONF_PAIR *cp;
371 char buffer[8192];
372 fr_token_t dflt_quote = rule->quote;
373
374 fr_assert(rule->dflt || rule->dflt_func);
375
376 if (fr_rule_required(rule)) {
377 cf_log_err(cs, "Configuration pair \"%s\" must have a value", rule->name1);
378 return -1;
379 }
380
381 /*
382 * If no default quote was set, determine it from the type
383 */
384 if (dflt_quote == T_INVALID) {
385 if (fr_type_is_quoted(rule->type)) {
386 dflt_quote = T_DOUBLE_QUOTED_STRING;
387 } else {
388 dflt_quote = T_BARE_WORD;
389 }
390 }
391
392 /*
393 * Use the dynamic default function if set
394 */
395 if (rule->dflt_func) {
396 if (rule->dflt_func(out, parent, cs, dflt_quote, rule) < 0) {
397 cf_log_perr(cs, "Failed producing default for \"%s\"", rule->name1);
398 return -1;
399 }
400
401 return 0;
402 }
403
404 expanded = cf_expand_variables("<internal>", lineno, cs, buffer, sizeof(buffer), rule->dflt, -1, NULL,
405 (dflt_quote != T_BARE_WORD));
406 if (!expanded) {
407 cf_log_err(cs, "Failed expanding variable %s", rule->name1);
408 return -1;
409 }
410
411 cp = cf_pair_alloc(cs, rule->name1, expanded, T_OP_EQ, T_BARE_WORD, dflt_quote);
412 if (!cp) return -1;
413
414 /*
415 * Set the ret to indicate we used a default value
416 */
417 *out = cp;
418
419 return 1;
420}
421
422static int cf_pair_unescape(CONF_PAIR *cp, conf_parser_t const *rule)
423{
424 char const *p;
425 char *str, *unescaped, *q;
426
427 if (!cp->value) return 0;
428
429 if (cp->rhs_quote != T_DOUBLE_QUOTED_STRING) return 0;
430
431 if (!(rule->flags & CONF_FLAG_TMPL)) {
432 if (rule->type != FR_TYPE_STRING) return 0;
433 }
434
435 if (strchr(cp->value, '\\') == NULL) return 0;
436
437 str = talloc_strdup(cp, cp->value);
438 if (!str) return -1;
439
440 p = cp->value;
441 q = str;
442 while (*p) {
443 if (*p != '\\') {
444 *(q++) = *(p++);
445 continue;
446 }
447
448 p++;
449 if (*p == '\0') {
450 *q++ = '\\';
451 continue;
452 }
453 switch (*p) {
454 case 'r':
455 *q++ = '\r';
456 break;
457 case 'n':
458 *q++ = '\n';
459 break;
460 case 't':
461 *q++ = '\t';
462 break;
463
464 default:
465 if ((*p >= '0') && (*p <= '7')) {
466 unsigned long oct;
467 char *end;
468
469 oct = strtoul(p, &end, 8);
470 if (oct == ULONG_MAX) {
471 cf_log_err(cp, "Failed parsing octal string");
472 error:
473 talloc_free(str);
474 return -1;
475 }
476
477 if (!oct) {
478 cf_log_err(cp, "Cannot have embedded zeros in value at %s", p);
479 goto error;
480 }
481
482 if (oct > UINT8_MAX) {
483 cf_log_err(cp, "Invalid octal number in value at %s", p);
484 goto error;
485 }
486
487 *q++ = oct;
488 p = end;
489 continue;
490 } else {
491 *q++ = *p;
492 }
493 break;
494 }
495 p++;
496 }
497 *q = '\0';
498
499 unescaped = talloc_strdup(cp, str); /* no embedded NUL */
500 talloc_free(str);
501 if (!unescaped) return -1;
502
503 /*
504 * Replace the old value with the new one.
505 */
507 cp->value = unescaped;
508
509 return 0;
510}
511
512/** Parses a #CONF_PAIR into a C data type, with a default value.
513 *
514 * @param[in] ctx To allocate arrays and values in.
515 * @param[out] out Where to write the result.
516 * Must not be NULL unless rule->runc is provided.
517 * @param[in] base address of the structure out points into.
518 * May be NULL in the case of manual parsing.
519 * @param[in] cs to search for matching #CONF_PAIR in.
520 * @param[in] rule to parse #CONF_PAIR with.
521 * @return
522 * - 1 if default value was used, or if there was no CONF_PAIR or dflt.
523 * - 0 on success.
524 * - -1 on error.
525 * - -2 if deprecated.
526 */
527static int CC_HINT(nonnull(4,5)) cf_pair_parse_internal(TALLOC_CTX *ctx, void *out, void *base,
528 CONF_SECTION *cs, conf_parser_t const *rule)
529{
530 bool required, v3_deprecated, was_dflt = false;
531 size_t count = 0;
532 CONF_PAIR *cp = NULL, *dflt_cp = NULL;
533
534#ifndef NDEBUG
535 char const *dflt = rule->dflt;
536 fr_token_t dflt_quote = rule->quote;
537#endif
538 cf_parse_t func = rule->func ? rule->func : cf_pair_parse_value;
539
540 fr_assert(!fr_rule_is_tmpl(rule) || !dflt || (dflt_quote != T_INVALID)); /* We ALWAYS need a quoting type for templates */
541
542 /*
543 * Functions don't necessarily *need* to write
544 * anywhere, so their data pointer can be NULL.
545 */
546 if (!out) {
547 if (!rule->func) {
548 cf_log_err(cs, "Rule doesn't specify output destination");
549 return -1;
550 }
551 }
552
553 required = fr_rule_required(rule);
554 v3_deprecated = fr_rule_v3_deprecated(rule);
555
556 cp = cf_pair_find(cs, rule->name1);
557 if (cp && cp->item.parsed) {
558 return 0;
559 }
560 cp = NULL;
561
562 /*
563 * If the item is multi-valued we allocate an array
564 * to hold the multiple values.
565 */
566 if (fr_rule_multi(rule)) {
567 void **array;
568 size_t i = 0;
569
570 /*
571 * Easier than re-allocing
572 */
573 count = cf_pair_count(cs, rule->name1);
574
575 /*
576 * Multivalued, but there's no value, create a
577 * default pair.
578 */
579 if (!count) {
580 if (v3_deprecated) return 0;
581
582 if (!fr_rule_dflt(rule)) {
583 if (required) {
584 need_value:
585 cf_log_err(cs, "Configuration item \"%s\" must have a value", rule->name1);
586 return -1;
587 }
588 return 1;
589 }
590
591 if (cf_pair_default(&dflt_cp, base, cs, rule) < 0) return -1;
592 count = cf_pair_count(cs, rule->name1); /* Dynamic functions can add multiple defaults */
593 if (!count) {
594 if (fr_rule_not_empty(rule)) {
595 cf_log_err(cs, "Configuration item \"%s\" cannot be empty", rule->name1);
596 return -1;
597 }
598 return 0;
599 }
600 }
601
602 if (v3_deprecated) {
603 /*
604 * Emit the deprecated warning in the
605 * context of the first pair.
606 */
607 cp = cf_pair_find(cs, rule->name1);
608 fr_assert(cp);
609
610 v3_deprecated:
611 cf_log_err(cp, "Configuration pair \"%s\" is from v3, and cannot be used in v4", cp->attr);
612 return -2;
613 }
614
615 /*
616 * No output, so don't bother allocing the array
617 */
618 if (!out) {
619 array = NULL;
620
621 /*
622 * Tmpl is outside normal range
623 */
624 } else if (fr_rule_is_tmpl(rule)) {
625 MEM(array = (void **)talloc_zero_array(ctx, tmpl_t *, count));
626
627 /*
628 * Allocate an array of values.
629 *
630 * We don't NULL terminate. Consumer must use
631 * talloc_array_length().
632 */
633 } else {
634 array = fr_type_array_alloc(ctx, rule->type, count);
635 if (unlikely(array == NULL)) {
636 cf_log_perr(cp, "Failed allocating value array");
637 return -1;
638 }
639 }
640
641 while ((cp = cf_pair_find_next(cs, cp, rule->name1))) {
642 int ret;
643 void *entry;
644 TALLOC_CTX *value_ctx = array;
645
646 /*
647 * Figure out where to write the output
648 */
649 if (!array) {
650 entry = NULL;
651 } else if ((rule->type == FR_TYPE_VOID) || (rule->flags & CONF_FLAG_TMPL)) {
652 entry = &array[i++];
653 } else {
654 entry = ((uint8_t *) array) + (i++ * fr_value_box_field_sizes[rule->type]);
655 }
656
657 if (cf_pair_unescape(cp, rule) < 0) return -1;
658
659 /*
660 * Switch between custom parsing function
661 * and the standard value parsing function.
662 */
663 cf_pair_debug_log(cs, cp, rule);
664
665 if (cp->item.parsed) continue;
666 ret = func(value_ctx, entry, base, cf_pair_to_item(cp), rule);
667 if (ret < 0) {
668 talloc_free(array);
669 return -1;
670 }
671 cp->item.parsed = true;
672 }
673 if (array) *(void **)out = array;
674 /*
675 * Single valued config item gets written to
676 * the data pointer directly.
677 */
678 } else {
679 CONF_PAIR *next;
680 int ret;
681
682 cp = cf_pair_find(cs, rule->name1);
683 if (!cp) {
684 if (v3_deprecated) return 0;
685
686 if (!fr_rule_dflt(rule)) {
687 if (required) goto need_value;
688 return 1;
689 }
690
691 if (cf_pair_default(&dflt_cp, base, cs, rule) < 0) return -1;
692 cp = dflt_cp;
693 if (!cp) {
694 if (fr_rule_not_empty(rule)) {
695 cf_log_err(cs, "Configuration item \"%s\" cannot be empty", rule->name1);
696 return -1;
697 }
698
699 return 0;
700 }
701 was_dflt = true;
702 } else {
703 if (cf_pair_unescape(cp, rule) < 0) return -1;
704 }
705
706 next = cf_pair_find_next(cs, cp, rule->name1);
707 if (next) {
708 cf_log_err(cf_pair_to_item(next), "Invalid duplicate configuration item '%s'", rule->name1);
709 return -1;
710 }
711 if (v3_deprecated) goto v3_deprecated;
712
713 cf_pair_debug_log(cs, cp, rule);
714
715 if (cp->item.parsed) return 0;
716 ret = func(ctx, out, base, cf_pair_to_item(cp), rule);
717 if (ret < 0) return -1;
718 cp->item.parsed = true;
719 }
720
721 return was_dflt ? 1 : 0;
722}
723
724/** Parses a #CONF_PAIR into a C data type, with a default value.
725 *
726 * Takes fields from a #conf_parser_t struct and uses them to parse the string value
727 * of a #CONF_PAIR into a C data type matching the type argument.
728 *
729 * The format of the types are the same as #fr_value_box_t types.
730 *
731 * @note The dflt value will only be used if no matching #CONF_PAIR is found. Empty strings will not
732 * result in the dflt value being used.
733 *
734 * **fr_type_t to data type mappings**
735 * | fr_type_t | Data type | Dynamically allocated |
736 * | ----------------------- | ------------------ | ---------------------- |
737 * | FR_TYPE_BOOL | ``bool`` | No |
738 * | FR_TYPE_UINT32 | ``uint32_t`` | No |
739 * | FR_TYPE_UINT16 | ``uint16_t`` | No |
740 * | FR_TYPE_UINT64 | ``uint64_t`` | No |
741 * | FR_TYPE_INT32 | ``int32_t`` | No |
742 * | FR_TYPE_STRING | ``char const *`` | Yes |
743 * | FR_TYPE_IPV4_ADDR | ``fr_ipaddr_t`` | No |
744 * | FR_TYPE_IPV4_PREFIX | ``fr_ipaddr_t`` | No |
745 * | FR_TYPE_IPV6_ADDR | ``fr_ipaddr_t`` | No |
746 * | FR_TYPE_IPV6_PREFIX | ``fr_ipaddr_t`` | No |
747 * | FR_TYPE_COMBO_IP_ADDR | ``fr_ipaddr_t`` | No |
748 * | FR_TYPE_COMBO_IP_PREFIX | ``fr_ipaddr_t`` | No |
749 * | FR_TYPE_TIME_DELTA | ``fr_time_delta_t``| No |
750 *
751 * @param[in] ctx To allocate arrays and values in.
752 * @param[in] cs to search for matching #CONF_PAIR in.
753 * @param[in] name of #CONF_PAIR to search for.
754 * @param[in] type Data type to parse #CONF_PAIR value as.
755 * Should be one of the following ``data`` types,
756 * and one or more of the following ``flag`` types or'd together:
757
758 * - ``data`` #FR_TYPE_BOOL - @copybrief FR_TYPE_BOOL
759 * - ``data`` #FR_TYPE_UINT32 - @copybrief FR_TYPE_UINT32
760 * - ``data`` #FR_TYPE_UINT16 - @copybrief FR_TYPE_UINT16
761 * - ``data`` #FR_TYPE_UINT64 - @copybrief FR_TYPE_UINT64
762 * - ``data`` #FR_TYPE_INT32 - @copybrief FR_TYPE_INT32
763 * - ``data`` #FR_TYPE_STRING - @copybrief FR_TYPE_STRING
764 * - ``data`` #FR_TYPE_IPV4_ADDR - @copybrief FR_TYPE_IPV4_ADDR (IPv4 address with prefix 32).
765 * - ``data`` #FR_TYPE_IPV4_PREFIX - @copybrief FR_TYPE_IPV4_PREFIX (IPv4 address with variable prefix).
766 * - ``data`` #FR_TYPE_IPV6_ADDR - @copybrief FR_TYPE_IPV6_ADDR (IPv6 address with prefix 128).
767 * - ``data`` #FR_TYPE_IPV6_PREFIX - @copybrief FR_TYPE_IPV6_PREFIX (IPv6 address with variable prefix).
768 * - ``data`` #FR_TYPE_COMBO_IP_ADDR - @copybrief FR_TYPE_COMBO_IP_ADDR (IPv4/IPv6 address with
769 * prefix 32/128).
770 * - ``data`` #FR_TYPE_COMBO_IP_PREFIX - @copybrief FR_TYPE_COMBO_IP_PREFIX (IPv4/IPv6 address with
771 * variable prefix).
772 * - ``data`` #FR_TYPE_TIME_DELTA - @copybrief FR_TYPE_TIME_DELTA
773 * - ``flag`` #CONF_FLAG_TMPL - @copybrief CONF_FLAG_TMPL
774 * Feeds the value into #tmpl_afrom_substr. Value can be
775 * obtained when processing requests, with #tmpl_expand or #tmpl_aexpand.
776 * - ``flag`` #CONF_FLAG_V3_DEPRECATED - @copybrief CONF_FLAG_V3_DEPRECATED
777 * - ``flag`` #CONF_FLAG_REQUIRED - @copybrief CONF_FLAG_REQUIRED
778 * - ``flag`` #CONF_FLAG_ATTRIBUTE - @copybrief CONF_FLAG_ATTRIBUTE
779 * - ``flag`` #CONF_FLAG_SECRET - @copybrief CONF_FLAG_SECRET
780 * - ``flag`` #CONF_FLAG_FILE_READABLE - @copybrief CONF_FLAG_FILE_READABLE
781 * - ``flag`` #CONF_FLAG_FILE_WRITABLE - @copybrief CONF_FLAG_FILE_WRITABLE
782 * - ``flag`` #CONF_FLAG_NOT_EMPTY - @copybrief CONF_FLAG_NOT_EMPTY
783 * - ``flag`` #CONF_FLAG_MULTI - @copybrief CONF_FLAG_MULTI
784 * - ``flag`` #CONF_FLAG_IS_SET - @copybrief CONF_FLAG_IS_SET
785 * @param[out] data Pointer to a global variable, or pointer to a field in the struct being populated with values.
786 * @param[in] dflt value to use, if no #CONF_PAIR is found.
787 * @param[in] dflt_quote around the dflt value.
788 * @return
789 * - 1 if default value was used, or if there was no CONF_PAIR or dflt.
790 * - 0 on success.
791 * - -1 on error.
792 * - -2 if deprecated.
793 */
794int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
795 unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
796{
797 conf_parser_t rule = {
798 .name1 = name,
799 .type = type,
800 .dflt = dflt,
801 .quote = dflt_quote
802 };
803
804 return cf_pair_parse_internal(ctx, data, NULL, cs, &rule);
805}
806
807/** Pre-allocate a config section structure to allow defaults to be set
808 *
809 * @param cs The parent subsection.
810 * @param base pointer or variable.
811 * @param rule that may have defaults in this config section.
812 * @return
813 * - 0 on success.
814 * - -1 on failure.
815 */
816static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t const *rule)
817{
818 CONF_PAIR *cp;
819
820 /*
821 * This rule refers to a named subsection
822 */
823 if ((rule->flags & CONF_FLAG_SUBSECTION)) {
824 char const *name2 = NULL;
825 CONF_SECTION *subcs;
826
827 /*
828 * Optional MUST be listed before required ones
829 */
830 if ((rule->flags & CONF_FLAG_OPTIONAL) != 0) {
831 return 0;
832 }
833
834 subcs = cf_section_find(cs, rule->name1, rule->name2);
835
836 /*
837 * Set the is_set field for the subsection.
838 */
839 if (rule->flags & CONF_FLAG_IS_SET) {
840 bool *is_set;
841
842 is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset;
843 if (is_set) *is_set = (subcs != NULL);
844 }
845
846 /*
847 * It exists, we don't have to do anything else.
848 */
849 if (subcs) return 0;
850
851 /*
852 * If there is no subsection, either complain,
853 * allow it, or create it with default values.
854 */
855 if (rule->flags & CONF_FLAG_REQUIRED) {
856 cf_log_err(cs, "Missing %s {} subsection", rule->name1);
857 return -1;
858 }
859
860 /*
861 * It's OK for this to be missing. Don't
862 * initialize it.
863 */
864 if ((rule->flags & CONF_FLAG_OK_MISSING) != 0) return 0;
865
866 /*
867 * If there's no subsection in the
868 * config, BUT the conf_parser_t wants one,
869 * then create an empty one. This is so
870 * that we can track the strings,
871 * etc. allocated in the subsection.
872 */
873 if (DEBUG_ENABLED4) cf_log_debug(cs, "Allocating fake section \"%s\"", rule->name1);
874
875 /*
876 * If name1 is CF_IDENT_ANY, then don't
877 * alloc the section as we have no idea
878 * what it should be called.
879 */
880 if (rule->name1 == CF_IDENT_ANY) return 0;
881
882 /*
883 * Don't specify name2 if it's CF_IDENT_ANY
884 */
885 if (rule->name2 != CF_IDENT_ANY) name2 = rule->name2;
886 subcs = cf_section_alloc(cs, cs, rule->name1, name2);
887 if (!subcs) return -1;
888
889 return 0;
890 }
891
892 /*
893 * This rule refers to another conf_parse_t which is included in-line in
894 * this section.
895 */
896 if ((rule->flags & CONF_FLAG_REF) != 0) {
897 conf_parser_t const *rule_p;
898 uint8_t *sub_base = base;
899
900 fr_assert(rule->subcs != NULL);
901
902 sub_base += rule->offset;
903
904 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
905 int ret = cf_section_parse_init(cs, sub_base, rule_p);
906 if (ret < 0) return ret;
907 }
908 return 0;
909 }
910
911 /*
912 * Don't re-initialize data which was already parsed.
913 */
914 cp = cf_pair_find(cs, rule->name1);
915 if (cp && cp->item.parsed) return 0;
916
917 if ((rule->type != FR_TYPE_STRING) &&
918 (!(rule->flags & CONF_FLAG_FILE_READABLE)) &&
919 (!(rule->flags & CONF_FLAG_FILE_WRITABLE))) {
920 return 0;
921 }
922
923 /*
924 * CONF_FLAG_NO_OUTPUT means the rule has no framework-managed
925 * output slot - nothing to NULL-init.
926 */
927 if (rule->flags & CONF_FLAG_NO_OUTPUT) return 0;
928
929 if (rule->data) {
930 *(char **) rule->data = NULL;
931 } else if (base) {
932 *(char **) (((char *)base) + rule->offset) = NULL;
933 } else {
934 return 0;
935 }
936
937 return 0;
938}
939
941{
942 cf_item_foreach(&cs->item, ci) {
943 /*
944 * Don't recurse on sections. We can only safely
945 * check conf pairs at the same level as the
946 * section that was just parsed.
947 */
948 if (ci->type == CONF_ITEM_SECTION) continue;
949 if (ci->type == CONF_ITEM_PAIR) {
950 CONF_PAIR *cp;
951
952 cp = cf_item_to_pair(ci);
953 if (cp->item.parsed || cp->item.referenced || (ci->lineno < 0)) continue;
954
955 WARN("%s[%d]: The item '%s' is defined, but is unused by the configuration",
956 ci->filename, ci->lineno,
957 cp->attr);
958 }
959
960 /*
961 * Skip everything else.
962 */
963 }
964}
965
966/** Parse a subsection
967 *
968 * @note Turns out using nested structures (instead of pointers) for subsections, was actually
969 * a pretty bad design decision, and will need to be fixed at some future point.
970 * For now we have a horrible hack where only multi-subsections get an array of structures
971 * of the appropriate size.
972 *
973 * @param[in] ctx to allocate any additional structures under.
974 * @param[out] out pointer to a struct/pointer to fill with data.
975 * @param[in] base address of the structure out points into.
976 * May be NULL in the case of manual parsing.
977 * @param[in] cs to parse.
978 * @param[in] rule to parse the subcs with.
979 * @return
980 * - 0 on success.
981 * - -1 on general error.
982 * - -2 if a deprecated #CONF_ITEM was found.
983 */
984static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
985{
986 CONF_SECTION *subcs = NULL;
987 int count = 0, i = 0, ret;
988
989 size_t subcs_size = rule->subcs_size;
990 conf_parser_t const *rules = rule->subcs;
991
992 /*
993 * CF_IDENT_ANY section rules act as a catch-all: skip any
994 * subsection that's already been claimed and marked parsed
995 * by an earlier specific rule, so the wildcard only handles
996 * the leftovers. CONF_FLAG_ALWAYS_PARSE overrides this and
997 * makes the rule observe every matching subsection.
998 */
999 bool const skip_parsed = (rule->name1 == CF_IDENT_ANY) &&
1000 !(rule->flags & CONF_FLAG_ALWAYS_PARSE);
1001
1002 bool const no_output = (rule->flags & CONF_FLAG_NO_OUTPUT);
1003
1004 uint8_t **array = NULL;
1005
1007
1008 if (skip_parsed) {
1009 while ((subcs = cf_section_find_next(cs, subcs, rule->name1, rule->name2))) {
1010 if (!cf_item_is_parsed(cf_section_to_item(subcs))) break;
1011 }
1012 } else {
1013 subcs = cf_section_find(cs, rule->name1, rule->name2);
1014 }
1015 if (!subcs) return 0;
1016
1017 /*
1018 * Handle the single subsection case (which is simple)
1019 */
1020 if (!(rule->flags & CONF_FLAG_MULTI)) {
1021 uint8_t *buff = NULL;
1022
1023 if (DEBUG_ENABLED4) cf_log_debug(cs, "Evaluating rules for %s section. Output %p",
1024 cf_section_name1(subcs), out);
1025
1026 /*
1027 * Add any rules, so the func can just call cf_section_parse
1028 * if it wants to continue after doing its stuff.
1029 */
1030 if (cf_section_rules_push(subcs, rules) < 0) return -1;
1031 if (rule->func) return rule->func(ctx, out, base, cf_section_to_item(subcs), rule);
1032
1033 /*
1034 * FIXME: We shouldn't allow nested structures like this.
1035 * Each subsection struct should be allocated separately so
1036 * we have a clean talloc hierarchy.
1037 */
1038 if (!subcs_size) return cf_section_parse(ctx, out, subcs);
1039
1040 if (out && !no_output) {
1041 MEM(buff = talloc_zero_array(ctx, uint8_t, subcs_size));
1042 if (rule->subcs_type) talloc_set_name_const(buff, rule->subcs_type);
1043 }
1044
1045 ret = cf_section_parse(buff, buff, subcs);
1046 if (ret < 0) {
1048 return ret;
1049 }
1050
1051 if (out && !no_output) *((uint8_t **)out) = buff;
1052
1053 return 0;
1054 }
1055
1056 fr_assert(subcs_size);
1057
1058 /*
1059 * Handle the multi subsection case (which is harder)
1060 */
1061 subcs = NULL;
1062 while ((subcs = cf_section_find_next(cs, subcs, rule->name1, rule->name2))) {
1063 if (skip_parsed && cf_item_is_parsed(cf_section_to_item(subcs))) continue;
1064 count++;
1065 }
1066
1067 /*
1068 * Allocate an array to hold the subsections
1069 */
1070 if (out && !no_output) {
1071 MEM(array = talloc_zero_array(ctx, uint8_t *, count));
1072 if (rule->subcs_type) talloc_set_name(array, "%s *", rule->subcs_type);
1073 }
1074 /*
1075 * Start parsing...
1076 *
1077 * Note, we allocate each subsection structure individually
1078 * so that they can be used as talloc contexts and we can
1079 * keep the talloc hierarchy clean.
1080 */
1081 subcs = NULL;
1082 while ((subcs = cf_section_find_next(cs, subcs, rule->name1, rule->name2))) {
1083 uint8_t *buff = NULL;
1084
1085 if (skip_parsed && cf_item_is_parsed(cf_section_to_item(subcs))) continue;
1086
1087 if (DEBUG_ENABLED4) cf_log_debug(cs, "Evaluating rules for %s[%i] section. Output %p",
1088 cf_section_name1(subcs),
1089 i, out);
1090
1091 if (array) {
1092 MEM(buff = talloc_zero_array(array, uint8_t, subcs_size));
1093 if (rule->subcs_type) talloc_set_name_const(buff, rule->subcs_type);
1094 array[i++] = buff;
1095 }
1096
1097 /*
1098 * Add any rules, so the func can just call cf_section_parse
1099 * if it wants to continue after doing its stuff.
1100 */
1101 if (cf_section_rules_push(subcs, rules) < 0) {
1102 talloc_free(array);
1103 return -1;
1104 }
1105 if (rule->func) {
1106 ret = rule->func(ctx, buff, base, cf_section_to_item(subcs), rule);
1107 if (ret < 0) {
1108 talloc_free(array);
1109 return ret;
1110 }
1111 continue;
1112 }
1113
1114 ret = cf_section_parse(buff, buff, subcs);
1115 if (ret < 0) {
1116 talloc_free(array);
1117 return ret;
1118 }
1119 }
1120
1121 if (out && !no_output) *((uint8_t ***)out) = array;
1122
1123 return 0;
1124}
1125
1126static int cf_section_parse_rule(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
1127{
1128 int ret;
1129 bool *is_set = NULL;
1130 void *data = NULL;
1131
1132 /*
1133 * Ignore ON_READ parse rules if there's no subsequent
1134 * parse functions.
1135 */
1136 if (!rule->func && rule->on_read) return 0;
1137
1138 /*
1139 * Pre-allocate the config structure to hold default values
1140 */
1141 if (cf_section_parse_init(cs, base, rule) < 0) return -1;
1142
1143 if (rule->data) {
1144 data = rule->data; /* prefer this. */
1145 } else if (base &&
1146 (!(rule->flags & CONF_FLAG_NO_OUTPUT) || (rule->flags & CONF_FLAG_SUBSECTION))) {
1147 /*
1148 * CONF_FLAG_NO_OUTPUT on a pair rule means leave
1149 * data NULL so the framework won't write through
1150 * base+offset. For subsections it only suppresses
1151 * the end-of-MULTI array write (handled inside
1152 * cf_subsection_parse) - we still need to pass
1153 * `base` through so nested rules can address into it.
1154 */
1155 data = ((uint8_t *)base) + rule->offset;
1156 }
1157
1158 /*
1159 * Handle subsections specially
1160 */
1161 if (rule->flags & CONF_FLAG_SUBSECTION) {
1162 return cf_subsection_parse(ctx, data, base, cs, rule);
1163 }
1164
1165 /*
1166 * A pair rule with name1 == CF_IDENT_ANY is a catch-all:
1167 * feed every still-unparsed CONF_PAIR in this section to the
1168 * rule's parser func. Order matters - specific rules before
1169 * this entry have already claimed (and marked parsed) their
1170 * pairs, so the catch-all only sees the leftovers, unless
1171 * CONF_FLAG_ALWAYS_PARSE is set (in which case it sees every
1172 * pair regardless).
1173 *
1174 * The rule must provide a func; there's no sensible default
1175 * output offset when the pair's name varies. The func
1176 * receives one CONF_PAIR at a time via ci and can read the
1177 * name via cf_pair_attr().
1178 */
1179 if (!(rule->flags & CONF_FLAG_REF) && rule->name1 == CF_IDENT_ANY) {
1180 bool const always_parse = (rule->flags & CONF_FLAG_ALWAYS_PARSE);
1181 CONF_PAIR *cp = NULL;
1182
1183 if (!rule->func) {
1184 cf_log_err(cs, "CF_IDENT_ANY pair rule must provide a parse function");
1185 return -1;
1186 }
1187
1188 while ((cp = cf_pair_find_next(cs, cp, NULL))) {
1189 if (!always_parse && cf_item_is_parsed(cf_pair_to_item(cp))) continue;
1190
1191 if (rule->func(ctx, data, base, cf_pair_to_item(cp), rule) < 0) return -1;
1193 }
1194 return 0;
1195 }
1196
1197 /*
1198 * Ignore this rule if it's a reference, as the
1199 * rules it points to have been pushed by the
1200 * above function.
1201 */
1202 if ((rule->flags & CONF_FLAG_REF) != 0) {
1203 conf_parser_t const *rule_p;
1204 uint8_t *sub_base = base;
1205
1206 fr_assert(rule->subcs != NULL);
1207
1208 sub_base += rule->offset;
1209
1210 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
1211 if (fr_rule_v3_deprecated(rule_p)) continue; /* Skip v3 deprecated */
1212
1213 ret = cf_section_parse_rule(ctx, sub_base, cs, rule_p);
1214 if (ret < 0) return ret;
1215 }
1216
1217 /*
1218 * Ensure we have a proper terminator, type so we catch
1219 * missing terminators reliably
1220 */
1221 fr_cond_assert(rule_p->type == conf_term.type);
1222
1223 return 0;
1224 }
1225
1226 /*
1227 * Else it's a CONF_PAIR
1228 */
1229
1230 /*
1231 * Pair either needs an output destination or
1232 * there needs to be a function associated with
1233 * it.
1234 */
1235 if (!data && !rule->func) {
1236 cf_log_err(cs, "Rule doesn't specify output destination");
1237 return -1;
1238 }
1239
1240 /*
1241 * Get pointer to where we need to write out
1242 * whether the pointer was set.
1243 */
1244 if (rule->flags & CONF_FLAG_IS_SET) {
1245 is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset;
1246 }
1247
1248 /*
1249 * Parse the pair we found, or a default value.
1250 */
1251 ret = cf_pair_parse_internal(ctx, data, base, cs, rule);
1252 switch (ret) {
1253 case 1: /* Used default (or not present) */
1254 if (is_set) *is_set = false;
1255 ret = 0;
1256 break;
1257
1258 case 0: /* OK */
1259 if (is_set) *is_set = true;
1260 break;
1261
1262 case -1: /* Parse error */
1263 break;
1264
1265 case -2: /* Deprecated CONF ITEM */
1266 if (((rule + 1)->offset && ((rule + 1)->offset == rule->offset)) ||
1267 ((rule + 1)->data && ((rule + 1)->data == rule->data))) {
1268 cf_log_err(cs, "Replace \"%s\" with \"%s\"", rule->name1,
1269 (rule + 1)->name1);
1270 }
1271 break;
1272 }
1273
1274 return ret;
1275}
1276
1277/** Parse a configuration section into user-supplied variables
1278 *
1279 * @param[in] ctx to allocate any strings, or additional structures in.
1280 * Usually the same as base, unless base is a nested struct.
1281 * @param[out] base pointer to a struct to fill with data.
1282 * @param[in] cs to parse.
1283 * @return
1284 * - 0 on success.
1285 * - -1 on general error.
1286 * - -2 if a deprecated #CONF_ITEM was found.
1287 */
1288int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
1289{
1290 CONF_DATA const *rule_cd = NULL;
1291
1292 if (!cs->name2) {
1293 cf_log_debug(cs, "%.*s%s {", SECTION_SPACE(cs), parse_spaces, cs->name1);
1294 } else {
1295 cf_log_debug(cs, "%.*s%s %s {", SECTION_SPACE(cs), parse_spaces, cs->name1, cs->name2);
1296 }
1297
1298 /*
1299 * Loop over all the child rules of the section
1300 */
1301 while ((rule_cd = cf_data_find_next(cs, rule_cd, conf_parser_t, CF_IDENT_ANY))) {
1302 int ret;
1303 conf_parser_t *rule;
1304
1305 rule = cf_data_value(rule_cd);
1306
1307 ret = cf_section_parse_rule(ctx, base, cs, rule);
1308 if (ret < 0) return ret;
1309 }
1310
1311 cs->base = base;
1312
1313 /*
1314 * Warn about items in the configuration which weren't
1315 * checked during parsing.
1316 */
1318
1319 cf_log_debug(cs, "%.*s}", SECTION_SPACE(cs), parse_spaces);
1320
1322 return 0;
1323}
1324
1325/*
1326 * Pass2 fixups on tmpl_t
1327 *
1328 * We don't have (or need yet) cf_pair_parse_pass2(), so we just
1329 * do it for tmpls.
1330 */
1332 bool attribute, fr_dict_t const *dict_def)
1333{
1334 tmpl_t *vpt = *out;
1335
1336 fr_assert(vpt); /* We need something to resolve */
1337
1338 if (tmpl_resolve(vpt, &(tmpl_res_rules_t){ .dict_def = dict_def, .force_dict_def = (dict_def != NULL)}) < 0) {
1339 cf_log_perr(cp, "Failed processing configuration item '%s'", cp->attr);
1340 return -1;
1341 }
1342
1343 if (attribute) {
1344 if (!tmpl_is_attr(vpt)) {
1345 cf_log_err(cp, "Expected attr got %s",
1346 tmpl_type_to_str(vpt->type));
1347 return -1;
1348 }
1349 }
1350
1351 switch (vpt->type) {
1352 /*
1353 * All attributes should have been defined by this point.
1354 */
1356 cf_log_err(cp, "Unknown attribute '%s'", tmpl_attr_tail_unresolved(vpt));
1357 return -1;
1358
1360 /*
1361 * Try to realize the underlying type, if at all possible.
1362 */
1363 if (!attribute && type && (tmpl_cast_in_place(vpt, type, NULL) < 0)) {
1364 cf_log_perr(cp, "Failed processing configuration item '%s'", cp->attr);
1365 return -1;
1366 }
1367 break;
1368
1369 case TMPL_TYPE_ATTR:
1370 case TMPL_TYPE_DATA:
1371 case TMPL_TYPE_EXEC:
1373 case TMPL_TYPE_XLAT:
1375 break;
1376
1378 case TMPL_TYPE_REGEX:
1382 case TMPL_TYPE_MAX:
1383 fr_assert(0);
1384 /* Don't add default */
1385 }
1386
1387 return 0;
1388}
1389
1390/** Fixup xlat expansions and attributes
1391 *
1392 * @param[out] base start of structure to write #tmpl_t s to.
1393 * @param[in] cs CONF_SECTION to fixup.
1394 * @return
1395 * - 0 on success.
1396 * - -1 on failure (parse errors etc...).
1397 */
1399{
1400 CONF_DATA const *rule_cd = NULL;
1401
1402 while ((rule_cd = cf_data_find_next(cs, rule_cd, conf_parser_t, CF_IDENT_ANY))) {
1403 bool attribute, multi, is_tmpl, is_xlat;
1404 CONF_PAIR *cp;
1405 conf_parser_t *rule = cf_data_value(rule_cd);
1406 void *data;
1407 fr_type_t type = rule->type;
1408 conf_parser_flags_t flags = rule->flags;
1409 fr_dict_t const *dict = NULL;
1410
1411 is_tmpl = (flags & CONF_FLAG_TMPL);
1412 is_xlat = (flags & CONF_FLAG_XLAT);
1413 attribute = (flags & CONF_FLAG_ATTRIBUTE);
1414 multi = (flags & CONF_FLAG_MULTI);
1415
1416 /*
1417 * It's a section, recurse!
1418 */
1419 if (flags & CONF_FLAG_SUBSECTION) {
1420 uint8_t *subcs_base;
1421 CONF_SECTION *subcs = cf_section_find(cs, rule->name1, rule->name2);
1422
1423 /*
1424 * Select base by whether this is a nested struct,
1425 * or a pointer to another struct.
1426 */
1427 if (!base || (flags & CONF_FLAG_NO_OUTPUT)) {
1428 subcs_base = NULL;
1429 } else if (multi) {
1430 size_t j, len;
1431 uint8_t **array;
1432
1433 array = *(uint8_t ***)(((uint8_t *)base) + rule->offset);
1434 len = talloc_array_length(array);
1435
1436 for (j = 0; j < len; j++) if (cf_section_parse_pass2(array[j], subcs) < 0) return -1;
1437 continue;
1438 } else {
1439 subcs_base = (uint8_t *)base + rule->offset;
1440 }
1441
1442 if (cf_section_parse_pass2(subcs_base, subcs) < 0) return -1;
1443
1444 continue;
1445 }
1446
1447 /*
1448 * Find the CONF_PAIR, may still not exist if there was
1449 * no default set for the conf_parser_t.
1450 */
1451 cp = cf_pair_find(cs, rule->name1);
1452 if (!cp) continue;
1453
1454 /*
1455 * Figure out which data we need to fix.
1456 */
1457 data = rule->data; /* prefer this. */
1458 if (!data && base && !(rule->flags & CONF_FLAG_NO_OUTPUT)) data = ((char *)base) + rule->offset;
1459 if (!data) continue;
1460
1461 /*
1462 * Non-xlat expansions shouldn't have xlat!
1463 *
1464 * Except other libraries like libkafka may be the ones
1465 * doing the actual expansion, so we don't _know_
1466 * if the xlatlike value is destined for use in FreeRADIUS
1467 * or not, so we can't definitely determine if this is an
1468 * error.
1469 *
1470 * Code left in place to warn other people off re-adding
1471 * this check in future.
1472 */
1473#if 0
1474 if (!is_xlat && !is_tmpl) {
1475 /*
1476 * Ignore %{... in shared secrets.
1477 * They're never dynamically expanded.
1478 */
1479 if ((rule->flags & CONF_FLAG_SECRET) != 0) continue;
1480
1481 if (strstr(cp->value, "%{") != NULL) {
1482 cf_log_err(cp, "Found dynamic expansion in string which "
1483 "will not be dynamically expanded");
1484 return -1;
1485 }
1486 continue;
1487 }
1488#endif
1489
1490 /*
1491 * Search for dictionary data somewhere in the virtual
1492 * server.
1493 */
1495
1496 /*
1497 * Parse (and throw away) the xlat string (for validation).
1498 *
1499 * FIXME: All of these should be converted from CONF_FLAG_XLAT
1500 * to CONF_FLAG_TMPL.
1501 */
1502 if (is_xlat) {
1503 fr_slen_t slen;
1504 xlat_exp_head_t *xlat;
1505
1506 redo:
1507 xlat = NULL;
1508
1509 /*
1510 * xlat expansions should be parseable.
1511 */
1512 slen = xlat_tokenize(cs, &xlat,
1513 &FR_SBUFF_IN(cp->value, talloc_strlen(cp->value)), NULL,
1514 &(tmpl_rules_t) {
1515 .attr = {
1516 .dict_def = dict,
1517 .list_def = request_attr_request,
1518 .allow_unknown = false,
1519 .allow_unresolved = false,
1520 .allow_foreign = (dict == NULL)
1521 },
1522 });
1523 if (slen < 0) {
1524 char *spaces, *text;
1525
1526 fr_canonicalize_error(cs, &spaces, &text, slen, cp->value);
1527
1528 cf_log_err(cp, "Failed parsing expansion string:");
1529 cf_log_err(cp, "%s", text);
1530 cf_log_perr(cp, "%s^", spaces);
1531
1533 talloc_free(text);
1534 talloc_free(xlat);
1535 return -1;
1536 }
1537
1538 talloc_free(xlat);
1539
1540 /*
1541 * If the "multi" flag is set, check all of them.
1542 */
1543 if (multi) {
1544 cp = cf_pair_find_next(cs, cp, cp->attr);
1545 if (cp) goto redo;
1546 }
1547 continue;
1548
1549 /*
1550 * Parse the pair into a template
1551 */
1552 } else if (is_tmpl && !multi) {
1553 if (cf_parse_tmpl_pass2(cs, (tmpl_t **)data, cp, type, attribute, dict) < 0) {
1554 return -1;
1555 }
1556
1557 } else if (is_tmpl) {
1558 size_t i;
1559 char const *name = cp->attr;
1560 tmpl_t **array = *(tmpl_t ***) data;
1561
1562 for (i = 0; i < talloc_array_length(array); i++, cp = cf_pair_find_next(cs, cp, name)) {
1563 if (!cp) break;
1564
1565 if (cf_parse_tmpl_pass2(cs, &array[i], cp, type, attribute, dict) < 0) {
1566 return -1;
1567 }
1568 }
1569 }
1570 }
1571
1572 return 0;
1573}
1574
1575
1576/** Add a single rule to a #CONF_SECTION
1577 *
1578 * @param[in] cs to add rules to.
1579 * @param[in] rule to add.
1580 * @param[in] filename where the rule was pushed.
1581 * @param[in] lineno where the rule was pushed.
1582 * @return
1583 * - 0 on success.
1584 * - -1 if the rules added conflict.
1585 */
1586int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
1587{
1588 char const *name1, *name2;
1589
1590 if (!cs || !rule) return 0;
1591
1592 name1 = rule->name1 == CF_IDENT_ANY ? "__any__" : rule->name1;
1593 name2 = rule->name2 == CF_IDENT_ANY ? "__any__" : rule->name2;
1594
1595 if (DEBUG_ENABLED4) {
1596 cf_log_debug(cs, "Pushed parse rule to %s section: %s %s",
1597 cf_section_name1(cs),
1598 name1, rule->flags & CONF_FLAG_SUBSECTION ? "{}": "");
1599 }
1600
1601 /*
1602 * Qualifying with name prevents duplicate rules being added
1603 *
1604 * Fixme maybe?.. Can't have a section and pair with the same name.
1605 */
1606 if (!_cf_data_add_static(CF_TO_ITEM(cs), rule, "conf_parser_t", name1, filename, lineno)) {
1607 CONF_DATA const *cd;
1608 conf_parser_t *old;
1609
1610 cd = cf_data_find(CF_TO_ITEM(cs), conf_parser_t, name1);
1611 old = cf_data_value(cd);
1612 fr_assert(old != NULL);
1613
1614 /*
1615 * Shut up about duplicates.
1616 */
1617 if (memcmp(rule, old, sizeof(*rule)) == 0) {
1618 return 0;
1619 }
1620
1621 /*
1622 * Remove any ON_READ callbacks, and add the new
1623 * rule in its place.
1624 */
1625 if (old->on_read) {
1626 CONF_DATA *cd1;
1627
1628 /*
1629 * Over-write the rule in place.
1630 *
1631 * We'd like to call cf_item_remove(), but
1632 * that apparently doesn't work for
1633 * CONF_DATA. We don't need to
1634 * free/alloc one, so re-using this is
1635 * fine.
1636 */
1637 memcpy(&cd1, &cd, sizeof(cd1));
1638 cd1->data = rule;
1639 cd1->item.filename = filename;
1640 cd1->item.lineno = lineno;
1641 return 0;
1642 }
1643
1644 /*
1645 * If we have a duplicate sub-section, just
1646 * recurse and add the new sub-rules to the
1647 * existing sub-section.
1648 */
1649 if (rule->flags & CONF_FLAG_SUBSECTION) {
1650 CONF_SECTION *subcs;
1651
1652 subcs = cf_section_find(cs, name1, name2);
1653 if (!subcs) {
1654 if ((rule->flags & CONF_FLAG_OK_MISSING) != 0) return 0;
1655
1656 if (!name2 || (name2 == CF_IDENT_ANY)) {
1657 cf_log_err(cs, "Failed finding '%s' subsection", name1);
1658 } else {
1659 cf_log_err(cs, "Failed finding '%s %s' subsection", name1, name2);
1660 }
1661
1662 cf_item_debug(cs);
1663 return -1;
1664 }
1665
1666 /*
1667 * The old rules were delayed until we pushed a matching subsection which is actually used.
1668 */
1669 if ((old->flags & CONF_FLAG_OPTIONAL) != 0) {
1670 if (cf_section_rules_push(subcs, old->subcs) < 0) return -1;
1671 }
1672
1673 return cf_section_rules_push(subcs, rule->subcs);
1674 }
1675
1676 cf_log_err(cs, "Data of type %s with name \"%s\" already exists. "
1677 "Existing data added %s[%i]", "conf_parser_t",
1678 name1, cd->item.filename, cd->item.lineno);
1679
1680 cf_item_debug(cs);
1681 return -1;
1682 }
1683
1684 return 0;
1685}
1686
1687/** Add an array of parse rules to a #CONF_SECTION
1688 *
1689 * @param[in] cs to add rules to.
1690 * @param[in] rules to add. Last element should have NULL name field.
1691 * @param[in] filename where the rule was pushed.
1692 * @param[in] lineno where the rule was pushed.
1693 * @return
1694 * - 0 on success.
1695 * - -1 on failure.
1696 */
1697int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
1698{
1699 conf_parser_t const *rule_p;
1700
1701 if (!cs || !rules) return 0;
1702
1703 for (rule_p = rules; rule_p->name1; rule_p++) {
1704 if (fr_rule_v3_deprecated(rule_p)) continue; /* Skip v3 deprecated */
1705 if (_cf_section_rule_push(cs, rule_p, filename, lineno) < 0) return -1;
1706 }
1707
1708 /*
1709 * Ensure we have a proper terminator, type so we catch
1710 * missing terminators reliably
1711 */
1712 fr_cond_assert(rule_p->type == conf_term.type);
1713
1714 return 0;
1715}
1716
1717/** Generic function for parsing conf pair values as int
1718 *
1719 * @note This should be used for enum types as c99 6.4.4.3 states that the enumeration
1720 * constants are of type int.
1721 *
1722 */
1723int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1724 CONF_ITEM *ci, conf_parser_t const *rule)
1725{
1726 int32_t num;
1727 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1728
1729 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1730
1731 *((int *)out) = num;
1732
1733 return 0;
1734}
1735
1736/** Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
1737 *
1738 */
1739int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1740 CONF_ITEM *ci, conf_parser_t const *rule)
1741{
1742 int32_t num;
1743 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1744
1745 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1746
1747 *((int32_t *)out) = num;
1748
1749 return 0;
1750}
1751
1752/** Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
1753 *
1754 */
1755int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1756 CONF_ITEM *ci, conf_parser_t const *rule)
1757{
1758 int32_t num;
1759 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1760
1761 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1762 if (num < 0) {
1763 cf_log_err(ci, "Resolved value must be a positive integer, got %i", num);
1764 return -1;
1765 }
1766 *((uint32_t *)out) = (uint32_t)num;
1767
1768 return 0;
1769}
1770
1771/** Generic function for resolving UID strings to uid_t values
1772 *
1773 * Type should be FR_TYPE_VOID, struct field should be a uid_t.
1774 */
1775int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1776 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1777{
1778 if (fr_perm_uid_from_str(ctx, (uid_t *)out, cf_pair_value(cf_item_to_pair(ci))) < 0) {
1779 cf_log_perr(ci, "Failed resolving UID");
1780 return -1;
1781 }
1782
1783 return 0;
1784}
1785
1786/** Generic function for resolving GID strings to uid_t values
1787 *
1788 * Type should be FR_TYPE_VOID, struct field should be a gid_t.
1789 */
1790int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1791 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1792{
1793 if (fr_perm_gid_from_str(ctx, (gid_t *)out, cf_pair_value(cf_item_to_pair(ci))) < 0) {
1794 cf_log_perr(ci, "Failed resolving GID");
1795 return -1;
1796 }
1797
1798 return 0;
1799}
1800
1801/** Generic function for resolving permissions to a mode-t
1802 *
1803 * Type should be FR_TYPE_VOID, struct field should be a gid_t.
1804 */
1805int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1806 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1807{
1808 mode_t mode;
1809 char const *name = cf_pair_value(cf_item_to_pair(ci));
1810
1811 if (fr_perm_mode_from_str(&mode, name) < 0) {
1812 cf_log_perr(ci, "Invalid permissions string");
1813 return -1;
1814 }
1815
1816 *(mode_t *) out = mode;
1817
1818 return 0;
1819}
1820
1821/** NULL callback for sections
1822 *
1823 * This callback exists only as a place-holder to ensure that the
1824 * nested on_read functions are called. The conf file routines won't
1825 * recurse into every conf_parser_t section to check if there's an
1826 * "on_read" callback. So this place-holder is a signal to do that.
1827 *
1828 * @param[in] ctx to allocate data in.
1829 * @param[out] out Unused
1830 * @param[in] parent Base structure address.
1831 * @param[in] ci #CONF_SECTION containing the current section.
1832 * @param[in] rule unused.
1833 * @return
1834 * - 0 on success.
1835 * - -1 on failure.
1836 */
1837int cf_null_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
1838 UNUSED CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1839{
1840 return 0;
1841}
1842
1843/** Bit-pos indexed table of `CONF_FLAG_*` names.
1844 *
1845 * Index is `fr_high_bit_pos()` of the flag value, which matches the
1846 * `_Generic` dispatch on `fr_table_num_indexed_bit_pos_t` in
1847 * `fr_table_str_by_value`.
1848 */
1872
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:560
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define NUM_ELEMENTS(_t)
Definition build.h:406
char const * cf_expand_variables(char const *cf, int lineno, CONF_SECTION *outer_cs, char *output, size_t outsize, char const *input, ssize_t inlen, bool *soft_fail, bool soft_fail_env)
Definition cf_file.c:297
cf_file_check_err_t cf_file_check_unix_perm(char const *filename, UNUSED void *uctx)
Check if file exists, and is a socket.
Definition cf_file.c:972
cf_file_check_err_t cf_file_check(CONF_PAIR *cp, bool check_perms)
Do some checks on the file as an "input" file.
Definition cf_file.c:1068
cf_file_check_err_t cf_file_check_effective(char const *filename, cf_file_check_err_t(*cb)(char const *filename, void *uctx), void *uctx)
Perform an operation with the effect/group set to conf_check_gid and conf_check_uid.
Definition cf_file.c:839
cf_file_check_err_t cf_file_check_unix_connect(char const *filename, UNUSED void *uctx)
Check if we can connect to a unix socket.
Definition cf_file.c:899
@ CF_FILE_NO_UNIX_SOCKET
File is not a unix socket.
Definition cf_file.h:49
int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
Definition cf_parse.c:1755
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1288
char const * cf_parser_flag_to_enum_str(conf_parser_flags_t mask)
Return the source-identifier name for a single CONF_FLAG_* bit.
Definition cf_parse.c:1873
int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
Definition cf_parse.c:1739
static size_t cf_parser_flag_table_len
Definition cf_parse.c:1871
static int cf_pair_default(CONF_PAIR **out, void *parent, CONF_SECTION *cs, conf_parser_t const *rule)
Allocate a pair using the dflt value and quotation.
Definition cf_parse.c:365
#define PAIR_SPACE(_cs)
Definition cf_parse.c:47
static char const parse_spaces[]
Definition cf_parse.c:45
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
Definition cf_parse.c:1723
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type.
Definition cf_parse.c:212
static int cf_pair_unescape(CONF_PAIR *cp, conf_parser_t const *rule)
Definition cf_parse.c:422
static void cf_section_parse_warn(CONF_SECTION *cs)
Definition cf_parse.c:940
static conf_parser_t conf_term
Definition cf_parse.c:44
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving GID strings to uid_t values.
Definition cf_parse.c:1790
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition cf_parse.c:794
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
Definition cf_parse.c:50
int cf_null_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent, UNUSED CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
NULL callback for sections.
Definition cf_parse.c:1837
static int cf_pair_parse_internal(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type, with a default value.
Definition cf_parse.c:527
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
Definition cf_parse.c:1805
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
Definition cf_parse.c:1398
static fr_table_num_indexed_bit_pos_t const cf_parser_flag_table[]
Bit-pos indexed table of CONF_FLAG_* names.
Definition cf_parse.c:1849
static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t const *rule)
Pre-allocate a config section structure to allow defaults to be set.
Definition cf_parse.c:816
int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
Add a single rule to a CONF_SECTION.
Definition cf_parse.c:1586
#define SECTION_SPACE(_cs)
Definition cf_parse.c:48
int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
Add an array of parse rules to a CONF_SECTION.
Definition cf_parse.c:1697
int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
Parses a CONF_PAIR into a boxed value.
Definition cf_parse.c:127
static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parse a subsection.
Definition cf_parse.c:984
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving UID strings to uid_t values.
Definition cf_parse.c:1775
static int cf_parse_tmpl_pass2(UNUSED CONF_SECTION *cs, tmpl_t **out, CONF_PAIR *cp, fr_type_t type, bool attribute, fr_dict_t const *dict_def)
Definition cf_parse.c:1331
static int cf_section_parse_rule(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Definition cf_parse.c:1126
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:673
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:627
#define fr_rule_file_writable(_rule)
Definition cf_parse.h:492
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:633
void * data
Pointer to a static variable to write the parsed value to.
Definition cf_parse.h:624
#define fr_rule_file_readable(_rule)
Definition cf_parse.h:490
#define fr_rule_file_socket(_rule)
Definition cf_parse.h:494
#define fr_rule_dflt(_rule)
Definition cf_parse.h:506
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:616
#define fr_rule_not_empty(_rule)
Definition cf_parse.h:500
fr_type_t type
An fr_type_t value, controls the output type.
Definition cf_parse.h:614
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition cf_parse.h:618
#define fr_rule_multi(_rule)
Definition cf_parse.h:498
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:612
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition cf_parse.h:665
fr_table_num_sorted_t const * table
Definition cf_parse.h:669
#define fr_rule_file_exists(_rule)
Definition cf_parse.h:496
int(* cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Callback for performing custom parsing of a CONF_SECTION or CONF_PAIR.
Definition cf_parse.h:567
#define fr_rule_v3_deprecated(_rule)
Definition cf_parse.h:484
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:705
#define fr_rule_is_tmpl(_rule)
Definition cf_parse.h:512
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:611
#define fr_rule_is_attribute(_rule)
Definition cf_parse.h:508
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
Definition cf_parse.h:630
#define fr_rule_required(_rule)
Definition cf_parse.h:486
conf_parser_flags_t
Definition cf_parse.h:425
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:433
@ CONF_FLAG_FILE_SOCKET
File matching value must exist, and must be a unix socket.
Definition cf_parse.h:443
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:450
@ CONF_FLAG_V3_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition cf_parse.h:431
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
Definition cf_parse.h:461
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition cf_parse.h:437
@ CONF_FLAG_NO_OUTPUT
Rule has no framework-managed output destination.
Definition cf_parse.h:468
@ CONF_FLAG_IS_SET
Write whether this config item was left as the default to is_set_offset or is_set_ptr.
Definition cf_parse.h:455
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition cf_parse.h:435
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:451
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition cf_parse.h:447
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
Definition cf_parse.h:462
@ CONF_FLAG_FILE_READABLE
File matching value must exist, and must be readable.
Definition cf_parse.h:439
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:458
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:427
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
Definition cf_parse.h:445
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Definition cf_parse.h:448
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition cf_parse.h:459
@ CONF_FLAG_ALWAYS_PARSE
Run this rule even against items already marked parsed.
Definition cf_parse.h:463
@ CONF_FLAG_FILE_WRITABLE
File matching value must exist, and must be writable.
Definition cf_parse.h:441
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:610
bool printed
Was this item printed already in debug mode?
Definition cf_priv.h:88
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:107
void * base
Definition cf_priv.h:118
char const * name2
Second name token. Given foo bar {} would be bar.
Definition cf_priv.h:110
char const * attr
Attribute name.
Definition cf_priv.h:80
bool referenced
Was this item referenced in the config?
Definition cf_priv.h:69
fr_token_t rhs_quote
Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition cf_priv.h:85
bool parsed
Was this item used during parsing?
Definition cf_priv.h:68
char const * value
Attribute value.
Definition cf_priv.h:81
char const * name1
First name token. Given foo bar {} would be foo.
Definition cf_priv.h:109
void const * data
User data.
Definition cf_priv.h:162
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:78
char const * filename
The file the config item was parsed from.
Definition cf_priv.h:71
@ CONF_ITEM_PAIR
Definition cf_priv.h:41
@ CONF_ITEM_SECTION
Definition cf_priv.h:42
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:157
int lineno
The line number the config item began on.
Definition cf_priv.h:70
Internal data that is associated with a configuration section.
Definition cf_priv.h:156
Common header for all CONF_* types.
Definition cf_priv.h:54
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:77
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
Definition cf_util.c:1612
unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
Count the number of times an attribute occurs in a parent section.
Definition cf_util.c:1679
int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
Check to see if the CONF_PAIR value is present in the specified table.
Definition cf_util.c:2083
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1876
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:750
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1445
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1349
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1205
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1598
CONF_DATA const * _cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name, char const *filename, int lineno)
Add non-talloced user data to a config section.
Definition cf_util.c:1941
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1760
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:676
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1226
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1716
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition cf_util.c:734
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:343
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:298
#define cf_item_is_parsed(_cf)
Definition cf_util.h:194
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:421
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:350
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:201
#define CF_TO_ITEM(_cf)
Auto cast from the input type to CONF_ITEM (which is the base type)
Definition cf_util.h:65
#define cf_item_foreach(_parent, _iter)
Iterate over every child item of a CONF_SECTION (or any CONF_ITEM that has children).
Definition cf_util.h:109
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:346
#define cf_data_find_next(_cf, _prev, _type, _name)
Definition cf_util.h:301
#define cf_item_debug(_cf)
Definition cf_util.h:415
#define cf_item_mark_parsed(_cf)
Definition cf_util.h:191
#define CF_IDENT_ANY
Definition cf_util.h:80
fr_dict_t * dict
Definition common.c:31
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define MEM(x)
Definition debug.h:38
Test enumeration values.
Definition dict_test.h:92
talloc_free(hp)
#define DEBUG_ENABLED4
True if global debug level 1-4 messages are enabled.
Definition log.h:265
int fr_debug_lvl
Definition log.c:41
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition log.c:105
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
Definition log.h:69
fr_type_t
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_VOID
User data.
unsigned int uint32_t
unsigned char uint8_t
unsigned int mode_t
ssize_t fr_slen_t
#define UINT8_MAX
int fr_perm_mode_from_str(mode_t *out, char const *str)
Definition perm.c:62
int fr_perm_uid_from_str(TALLOC_CTX *ctx, uid_t *out, char const *name)
Resolve a user name to a GID.
Definition perm.c:453
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition perm.c:475
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition print.c:438
#define fr_assert(_expr)
Definition rad_assert.h:37
static char * secret
#define WARN(fmt,...)
static const char * spaces
Definition radict.c:177
static uint32_t mask
Definition rbmonkey.c:39
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition tmpl.h:661
#define tmpl_contains_data(vpt)
Definition tmpl.h:231
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_is_attr(vpt)
Definition tmpl.h:215
@ TMPL_TYPE_REGEX_UNCOMPILED
Regex where compilation is possible but hasn't been performed yet.
Definition tmpl.h:165
@ TMPL_TYPE_MAX
Marker for the last tmpl type.
Definition tmpl.h:206
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
Definition tmpl.h:192
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:149
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
Definition tmpl.h:153
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:157
@ TMPL_TYPE_REGEX_XLAT_UNRESOLVED
A regular expression with unresolved xlat functions or attribute references.
Definition tmpl.h:204
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:145
@ TMPL_TYPE_REGEX
Compiled (and possibly JIT'd) regular expression.
Definition tmpl.h:161
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:186
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
Definition tmpl.h:200
@ TMPL_TYPE_REGEX_XLAT
A regex containing xlat expansions.
Definition tmpl.h:169
@ TMPL_TYPE_EXEC_UNRESOLVED
An exec with unresolved xlat function or attribute references.
Definition tmpl.h:196
@ TMPL_TYPE_UNINITIALISED
Uninitialised.
Definition tmpl.h:141
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
fr_slen_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
Definition tmpl.h:892
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv))
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
#define tmpl_is_data(vpt)
Definition tmpl.h:213
static fr_slen_t vpt
Definition tmpl.h:1290
#define tmpl_value_type(_tmpl)
Definition tmpl.h:962
#define tmpl_is_data_unresolved(vpt)
Definition tmpl.h:224
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:346
int tmpl_cast_set(tmpl_t *vpt, fr_type_t type)
Set a cast for a tmpl.
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Definition tmpl.h:391
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:343
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:37
return count
Definition module.c:155
fr_aka_sim_id_type_t type
unsigned int allow_unknown
Allow unknown attributes i.e.
Definition tmpl.h:310
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition tmpl.h:302
#define FR_TABLE_INDEXED_BIT_POS_ENTRY(_v)
Build a single fr_table_num_indexed_bit_pos_t entry from an enum identifier.
Definition table.h:125
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
An element in a table indexed by bit position.
Definition table.h:83
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:288
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
Definition token.c:224
enum fr_token fr_token_t
@ T_INVALID
Definition token.h:37
@ T_SINGLE_QUOTED_STRING
Definition token.h:120
@ T_BARE_WORD
Definition token.h:118
@ T_OP_EQ
Definition token.h:81
@ T_BACK_QUOTED_STRING
Definition token.h:121
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
@ T_SOLIDUS_QUOTED_STRING
Definition token.h:122
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Tokenize an xlat expansion.
static fr_slen_t parent
Definition pair.h:860
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:558
void ** fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
Allocate an array of a given type.
Definition types.c:700
#define fr_type_is_string(_x)
Definition types.h:348
#define fr_type_is_quoted(_x)
Definition types.h:389
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
Definition value.c:151
fr_slen_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules)
Definition value.c:6141
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4358
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted[T_TOKEN_LAST]
Parse rules for non-quoted strings.
Definition value.c:513
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4404
static int fr_value_box_memcpy_out(void *out, fr_value_box_t const *vb)
Copy the value of a value box to a field in a C struct.
Definition value.h:829
#define fr_value_box_mark_safe_for(_box, _safe_for)
Definition value.h:1125
static fr_slen_t data
Definition value.h:1367
static fr_sbuff_err_t char ** out
Definition value.h:1062
static fr_sbuff_err_t char size_t * len
Definition value.h:1062
int nonnull(2, 5))
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.