The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
cf_util.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: 82d314f5384ba5d00bd08f480929d6546e077d41 $
19 * @file cf_util.c
20 * @brief Functions for building and managing the structure of internal format config items.
21 *
22 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24RCSID("$Id: 82d314f5384ba5d00bd08f480929d6546e077d41 $")
25
26#include <string.h>
27
28#include <freeradius-devel/server/cf_file.h>
29#include <freeradius-devel/server/cf_priv.h>
30#include <freeradius-devel/server/log.h>
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/atexit.h>
33#include <freeradius-devel/util/sbuff.h>
34
35static inline fr_cmp_ret_t cf_ident2_cmp(void const *a, void const *b);
36static fr_cmp_ret_t _cf_ident1_cmp(void const *a, void const *b);
37static fr_cmp_ret_t _cf_ident2_cmp(void const *a, void const *b);
38
39/** Return the next child that's of the specified type
40 *
41 * @param[in] parent to return children from.
42 * @param[in] current child to start searching from.
43 * @param[in] type to search for.
44 * @return
45 * - The next #CONF_ITEM that's a child of ci matching type.
46 * - NULL if no #CONF_ITEM matches that criteria.
47 */
49{
51 if (ci->type == type) return ci;
52 }
53
54 return NULL;
55}
56
57/** Return the previous child that's of the specified type
58 *
59 * @param[in] parent to return children from.
60 * @param[in] current child to start searching from.
61 * @param[in] type to search for.
62 * @return
63 * - The next #CONF_ITEM that's a child of ci matching type.
64 * - NULL if no #CONF_ITEM matches that criteria.
65 */
66static inline CC_HINT(always_inline)
68{
70 if (ci->type == type) return ci;
71 }
72
73 return NULL;
74}
75
76#define IS_WILDCARD(_ident) (_ident == CF_IDENT_ANY)
77
78/** Return the next child that's of the specified type with the specified identifiers
79 *
80 * @param[in] parent The section we're searching in.
81 * @param[in] type of #CONF_ITEM we're searching for.
82 * @param[in] ident1 The first identifier.
83 * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
84 * can be used to match any ident2 value.
85 * @return
86 * - The first matching item.
87 * - NULL if no items matched.
88 */
89static CONF_ITEM *cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
90{
91 CONF_SECTION cs_find;
92 CONF_PAIR cp_find;
93 CONF_DATA cd_find;
94 CONF_ITEM *find;
95 CONF_ITEM *found;
96
97 if (!parent) return NULL;
98 if (cf_item_has_no_children(parent)) return NULL;
99
100 if (!ident1) return cf_next(parent, NULL, type);
101
102 switch (type) {
104 memset(&cs_find, 0, sizeof(cs_find));
105 cs_find.item.type = CONF_ITEM_SECTION;
106 cs_find.name1 = ident1;
107 if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
108
109 find = (CONF_ITEM *)&cs_find;
110 break;
111
112 case CONF_ITEM_PAIR:
113 fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
114
115 memset(&cp_find, 0, sizeof(cp_find));
116 cp_find.item.type = CONF_ITEM_PAIR;
117 cp_find.attr = ident1;
118
119 find = (CONF_ITEM *)&cp_find;
120 break;
121
122 case CONF_ITEM_DATA:
123 memset(&cd_find, 0, sizeof(cd_find));
124 cd_find.item.type = CONF_ITEM_DATA;
125 cd_find.type = ident1;
126 if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
127
128 find = (CONF_ITEM *)&cd_find;
129 break;
130
131 default:
132 fr_assert_fail(NULL);
133 return NULL;
134 }
135
136 /*
137 * No ident1, iterate over the child list
138 */
139 if (IS_WILDCARD(ident1)) {
141 if (find->type != ci->type) continue;
142
143 if (cf_ident2_cmp(find, ci) == 0) return ci;
144 }
145
146 return NULL;
147 }
148
149 /*
150 * No ident2, use the ident1 tree. The tree itself may be
151 * NULL when the parent has only had non-indexed children
152 * added (e.g. CONF_COMMENT items don't populate the rbtree).
153 */
154 if (IS_WILDCARD(ident2)) {
155 if (!parent->ident1) return NULL;
156 fr_rb_find((void **)&found, parent->ident1, find);
157 return found;
158 }
159
160 /*
161 * Only sections have an ident2 tree.
162 */
163 if (parent->type != CONF_ITEM_SECTION) return NULL;
164
165 /*
166 * Both ident1 and ident2 use the ident2 tree. As above,
167 * the tree may be NULL when only non-indexed children exist.
168 */
169 if (!parent->ident2) return NULL;
170 fr_rb_find((void **)&found, parent->ident2, find);
171 return found;
172}
173
174/** Return the next child that's of the specified type with the specified identifiers
175 *
176 * @param[in] parent The section we're searching in.
177 * @param[in] prev item we found, or NULL to start from the beginning.
178 * @param[in] type of #CONF_ITEM we're searching for.
179 * @param[in] ident1 The first identifier.
180 * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
181 * can be used to match any ident2 value.
182 * @return
183 * - The first matching item.
184 * - NULL if no items matched.
185 */
186static CONF_ITEM *cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev,
187 CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
188{
189 CONF_SECTION cs_find;
190 CONF_PAIR cp_find;
191 CONF_DATA cd_find;
192 CONF_ITEM *find;
193
194 if (!parent) return NULL;
195
196 if (!prev) {
197 if (!ident1) return cf_next(parent, NULL, type);
198 return cf_find(parent, type, ident1, ident2);
199 }
200 if (!ident1) return cf_next(parent, prev, type);
201
202 switch (type) {
204 memset(&cs_find, 0, sizeof(cs_find));
205 cs_find.item.type = CONF_ITEM_SECTION;
206 cs_find.name1 = ident1;
207 if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
208
209 find = (CONF_ITEM *)&cs_find;
210 break;
211
212 case CONF_ITEM_PAIR:
213 fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
214
215 memset(&cp_find, 0, sizeof(cp_find));
216 cp_find.item.type = CONF_ITEM_PAIR;
217 cp_find.attr = ident1;
218
219 find = (CONF_ITEM *)&cp_find;
220 break;
221
222 case CONF_ITEM_DATA:
223 memset(&cd_find, 0, sizeof(cd_find));
224 cd_find.item.type = CONF_ITEM_DATA;
225 cd_find.type = ident1;
226 if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
227
228 find = (CONF_ITEM *)&cd_find;
229 break;
230
231 default:
232 fr_assert_fail(NULL);
233 return NULL;
234 }
235
236 if (IS_WILDCARD(ident1)) {
237 cf_item_foreach_next(parent, ci, prev) {
238 if (find->type != ci->type) continue;
239
240 if (cf_ident2_cmp(find, ci) == 0) return ci;
241 }
242
243 return NULL;
244 }
245
246 if (IS_WILDCARD(ident2)) {
247 cf_item_foreach_next(parent, ci, prev) {
248 if (_cf_ident1_cmp(ci, find) == 0) return ci;
249
250 }
251
252 return NULL;
253 }
254
255 cf_item_foreach_next(parent, ci, prev) {
256 if (_cf_ident2_cmp(ci, find) == 0) return ci;
257 }
258
259 return NULL;
260}
261
262/** Compare the first identifier of a child
263 *
264 * For CONF_ITEM_PAIR this is 'attr'.
265 * For CONF_ITEM_SECTION this is 'name1'.
266 * For CONF_ITEM_DATA this is 'type'.
267 *
268 * @param[in] one First CONF_ITEM to compare.
269 * @param[in] two Second CONF_ITEM to compare.
270 * @return CMP(one, two)
271 */
272static inline fr_cmp_ret_t _cf_ident1_cmp(void const *one, void const *two)
273{
274 int ret;
275
277
278 {
279 CONF_ITEM const *a = one;
280 CONF_ITEM const *b = two;
281
282 CMP_RETURN(a, b, type);
283 type = a->type;
284 }
285
286 switch (type) {
287 case CONF_ITEM_PAIR:
288 {
289 CONF_PAIR const *a = one;
290 CONF_PAIR const *b = two;
291
292 ret = strcmp(a->attr, b->attr);
293 return CMP(ret, 0);
294 }
295
297 {
298 CONF_SECTION const *a = one;
299 CONF_SECTION const *b = two;
300
301 ret = strcmp(a->name1, b->name1);
302 return CMP(ret, 0);
303 }
304
305 case CONF_ITEM_DATA:
306 {
307 CONF_DATA const *a = one;
308 CONF_DATA const *b = two;
309
310 ret = strcmp(a->type, b->type);
311 return CMP(ret, 0);
312 }
313
314 default:
315 fr_assert_fail(NULL);
316 return CMP_EQ;
317 }
318}
319
320/** Compare only the second identifier of a child
321 *
322 * For CONF_ITEM_SECTION this is 'name2'.
323 * For CONF_ITEM_DATA this is 'name'.
324 *
325 * @param[in] one First CONF_ITEM to compare.
326 * @param[in] two Second CONF_ITEM to compare.
327 * @return CMP(one,two)
328 */
329static inline fr_cmp_ret_t cf_ident2_cmp(void const *one, void const *two)
330{
331 CONF_ITEM const *ci = one;
332 int ret;
333
334 switch (ci->type) {
335 case CONF_ITEM_PAIR:
336 return CMP_EQ;
337
339 {
340 CONF_SECTION const *a = one;
341 CONF_SECTION const *b = two;
342
343 if (!b->name2 && a->name2) return CMP_GT;
344 if (b->name2 && !a->name2) return CMP_LT;
345 if (!b->name2 && !a->name2) return CMP_EQ;
346
347 ret = strcmp(a->name2, b->name2);
348 return CMP(ret, 0);
349 }
350
351 case CONF_ITEM_DATA:
352 {
353 CONF_DATA const *a = one;
354 CONF_DATA const *b = two;
355
356 if (!b->name && a->name) return CMP_GT;
357 if (b->name && !a->name) return CMP_LT;
358 if (!b->name && !a->name) return CMP_EQ;
359
360 ret = strcmp(a->name, b->name);
361 return CMP(ret, 0);
362 }
363
364 default:
365 fr_assert_fail(NULL);
366 return CMP_EQ;
367 }
368}
369
370/** Compare the first and second identifiers of a child
371 *
372 * For CONF_ITEM_SECTION this is 'name2'.
373 * For CONF_ITEM_DATA this is 'name'.
374 *
375 * @param[in] a First CONF_ITEM to compare.
376 * @param[in] b Second CONF_ITEM to compare.
377 * @return CMP(a, b)
378 */
379static fr_cmp_ret_t _cf_ident2_cmp(void const *a, void const *b)
380{
381 int ret;
382
383 ret = _cf_ident1_cmp(a, b);
384 if (ret != 0) return ret;
385
386 return cf_ident2_cmp(a, b);
387}
388
389/** Add a child
390 *
391 * @param[in] parent to add child to.
392 * @param[in] child to add.
393 */
395{
396 fr_assert(parent != child);
397
398 if (!parent || !child) return -1;
399
401 ERROR("%s[%d]: There are too many (%u) entries in this configuration section. "
402 "There is likely some structural issue with the configuration files",
403 parent->filename, parent->lineno, CF_SECTION_MAX_CHILDREN);
404 return -1;
405 }
406
407 /*
408 * New child, add child trees.
409 */
410 if (!parent->ident1) parent->ident1 = fr_rb_inline_alloc(parent, CONF_ITEM, ident1_node,
411 _cf_ident1_cmp, NULL);
412
413 fr_rb_insert(parent->ident1, child);
415 fr_dlist_insert_tail(&parent->children, child); /* Append to the list of children */
416
417 if (parent->type != CONF_ITEM_SECTION) return 0; /* Only sections can have ident2 trees */
418
419 if (!parent->ident2) parent->ident2 = fr_rb_inline_alloc(parent, CONF_ITEM, ident2_node,
420 _cf_ident2_cmp, NULL);
421
422 fr_rb_insert(parent->ident2, child); /* NULL ident2 is still a value */
423 return 0;
424}
425
426/** Remove item from parent and fixup trees
427 *
428 * @param[in] parent to remove child from.
429 * @param[in] child to remove.
430 * @return
431 * - The previous item (makes iteration easier)
432 * - NULL if the item wasn't set.
433 */
435{
436 CONF_ITEM *found = NULL;
437 CONF_ITEM *prev;
438 bool in_ident1, in_ident2;
439
440 if (!parent || cf_item_has_no_children(parent)) return NULL;
441 if (parent != child->parent) return NULL;
442
444 if (ci == child) {
445 found = ci;
446 break;
447 }
448 }
449
450 if (!found) return NULL;
451
452 /*
453 * Fixup the linked list
454 */
455 prev = fr_dlist_remove(&parent->children, child);
456
457 in_ident1 = (fr_rb_remove_by_inline_node(parent->ident1, &child->ident1_node) != NULL);
458
459 /*
460 * Only sections can have ident2 trees.
461 */
462 if (parent->type != CONF_ITEM_SECTION) {
463 in_ident2 = false;
464 } else {
465 in_ident2 = (fr_rb_remove_by_inline_node(parent->ident2, &child->ident2_node) != NULL);
466 }
467
468 /*
469 * Look for twins. They weren't in the tree initially,
470 * because "child" was there.
471 */
473 if (!in_ident1 && !in_ident2) break;
474
475 if (in_ident1 && (_cf_ident1_cmp(ci, child) == 0)) {
476 fr_rb_insert(parent->ident1, ci);
477 in_ident1 = false;
478 }
479
480 if (in_ident2 && (_cf_ident2_cmp(ci, child) == 0)) {
481 fr_rb_insert(parent->ident2, ci);
482 in_ident2 = false;
483 }
484 }
485
486 return prev;
487}
488
489/** Return the next child of the CONF_ITEM
490 *
491 * @param[in] parent to return children from.
492 * @param[in] curr child to start searching from.
493 * @return
494 * - The next #CONF_ITEM that's a child of cs.
495 * - NULL if no more #CONF_ITEM.
496 */
498{
499 if (!parent) return NULL;
500
501 return fr_dlist_next(&parent->children, curr);
502}
503
504/** Return the next child of cs
505 *
506 * @param[in] ci to return children from.
507 * @param[in] curr child to start searching from.
508 * @return
509 * - The next #CONF_ITEM that's a child of cs.
510 * - NULL if no more #CONF_ITEM.
511 */
513{
514 if (!ci) return NULL;
515
516 return fr_dlist_prev(&ci->children, curr);
517}
518
519/** Initialize a CONF_ITEM, so we don't have repeated code
520 *
521 * @param[in] ci the CONF_ITEM to initialize
522 * @param[in] type the type to set
523 * @param[in] parent the parent node hosting this one
524 * @param[in] filename which caused this node to be created
525 * @param[in] lineno where in the filename
526 */
527static void cf_item_init(CONF_ITEM *ci, CONF_ITEM_TYPE type, CONF_ITEM *parent, char const *filename, int lineno)
528{
529 ci->type = type;
530 ci->parent = parent;
531
532 fr_dlist_init(&ci->children, CONF_ITEM, entry);
533
534 if (filename) cf_filename_set(ci, filename);
535 if (lineno) cf_lineno_set(ci, lineno);
536}
537
538/** Return the top level #CONF_SECTION holding all other #CONF_ITEM
539 *
540 * @param[in] ci to traverse up from.
541 * @return
542 * - NULL if ci was NULL.
543 * - The top level #CONF_SECTION
544 */
546{
547 CONF_ITEM const *ci_p;
548
549 if (!ci) return NULL;
550
551 for (ci_p = ci; ci_p->parent; ci_p = ci_p->parent);
552
553 return cf_item_to_section(ci_p);
554}
555
556/** Return the parent of a #CONF_ITEM
557 *
558 * @param[in] ci to return the parent of.
559 * @return
560 * - NULL if ci was NULL or it has no parents.
561 * - The parent of ci.
562 */
564{
565 if (!ci) return NULL;
566
567 return ci->parent;
568}
569
570/** Return the lineno the #CONF_ITEM was parsed at
571 *
572 * @param[in] ci to return the location of.
573 * @return
574 * - -1 if the #CONF_ITEM was created programmatically.
575 * - >= 0 where in the config file the line was parsed from.
576 */
577int _cf_lineno(CONF_ITEM const *ci)
578{
579 if (!ci) return -1;
580
581 return ci->lineno;
582}
583
584/** Return the filename the #CONF_ITEM was parsed in
585 *
586 * @param[in] ci to return the location of.
587 * @return
588 * - NULL if the #CONF_ITEM was created programmatically.
589 * - The path of the config file the #CONF_ITEM was located in.
590 */
591char const *_cf_filename(CONF_ITEM const *ci)
592{
593 if (!ci) return NULL;
594
595 return ci->filename;
596}
597
598/** Determine if #CONF_ITEM is a #CONF_SECTION
599 *
600 * @param[in] ci to check.
601 * @return
602 * - true if ci is a #CONF_SECTION.
603 * - false if ci is another specialisation.
604 */
606{
607 if (!ci) return false;
608
609 return ci->type == CONF_ITEM_SECTION;
610}
611
612/** Determine if #CONF_ITEM is a #CONF_PAIR
613 *
614 * @param[in] ci to check.
615 * @return
616 * - true if ci is a #CONF_PAIR.
617 * - false if ci is another specialisation.
618 */
620{
621 if (!ci) return false;
622
623 return ci->type == CONF_ITEM_PAIR;
624}
625
626/** Determine if #CONF_ITEM is #CONF_DATA
627 *
628 * @param[in] ci to check.
629 * @return
630 * - true if ci is #CONF_DATA.
631 * - false if ci is another specialisation.
632 */
634{
635 if (!ci) return false;
636
637 return ci->type == CONF_ITEM_DATA;
638}
639
640/** Cast a #CONF_ITEM to a #CONF_PAIR
641 *
642 * @note Will assert if ci does not contain #CONF_PAIR.
643 *
644 * @param[in] ci to cast.
645 * @return
646 * - #CONF_PAIR.
647 * - NULL if ci was NULL.
648 *
649 * @hidecallergraph
650 */
652{
653 if (ci == NULL) return NULL;
654
656
657 return UNCONST(CONF_PAIR *, ci);
658}
659
660/** Cast a #CONF_ITEM to a #CONF_SECTION
661 *
662 * @note Will assert if ci does not contain #CONF_SECTION.
663 *
664 * @param[in] ci to cast.
665 * @return
666 * - #CONF_SECTION.
667 * - NULL if ci was NULL.
668 *
669 * @hidecallergraph
670 */
672{
673 if (ci == NULL) return NULL;
674
676
677 return UNCONST(CONF_SECTION *, ci);
678}
679
680/** Cast #CONF_ITEM to #CONF_DATA performing a type check
681 *
682 * @note Will assert if ci does not contain #CONF_DATA.
683 *
684 * @param[in] ci to cast.
685 * @return
686 * - #CONF_DATA.
687 * - NULL if ci was NULL.
688 *
689 * @hidecallergraph
690 */
692{
693 if (ci == NULL) return NULL;
694
696
697 return UNCONST(CONF_DATA *, ci);
698}
699
700/** Cast a #CONF_PAIR to a #CONF_ITEM
701 *
702 * @param[in] cp to cast.
703 * @return
704 * - The common #CONF_ITEM header.
705 * - NULL if cp was NULL.
706 *
707 * @hidecallergraph
708 */
710{
711 if (cp == NULL) return NULL;
712
713 return UNCONST(CONF_ITEM *, cp);
714}
715
716/** Cast a #CONF_SECTION to a #CONF_ITEM
717 *
718 * @param[in] cs to cast.
719 * @return
720 * - The common #CONF_ITEM header.
721 * - NULL if cs was NULL.
722 *
723 * @hidecallergraph
724 */
726{
727 if (cs == NULL) return NULL;
728
729 return UNCONST(CONF_ITEM *, cs);
730}
731
732/** Cast #CONF_DATA to a #CONF_ITEM
733 *
734 * @param[in] cd to cast.
735 * @return
736 * - The common #CONF_ITEM header.
737 * - NULL if cd was NULL.
738 *
739 * @hidecallergraph
740 */
742{
743 if (cd == NULL) return NULL;
744
745 return UNCONST(CONF_ITEM *, cd);
746}
747
748/** Determine if #CONF_ITEM is a #CONF_COMMENT.
749 */
751{
752 if (!ci) return false;
753 return ci->type == CONF_ITEM_COMMENT;
754}
755
756/** Cast a #CONF_ITEM to a #CONF_COMMENT (asserts on type mismatch).
757 */
759{
760 if (ci == NULL) return NULL;
762 return UNCONST(CONF_COMMENT *, ci);
763}
764
765/** Cast a #CONF_COMMENT back to a #CONF_ITEM.
766 */
768{
769 if (c == NULL) return NULL;
770 return UNCONST(CONF_ITEM *, c);
771}
772
773char const *cf_comment_text(CONF_COMMENT const *c)
774{
775 if (c == NULL) return NULL;
776 return c->text;
777}
778
779/*
780 * Off by default - the runtime server parser drops comments as it
781 * always has. Utilities call cf_preserve_comments_set() before
782 * cf_file_read() when they want the round-trip.
783 */
784static bool cf_preserve_comments = false;
785
786void cf_preserve_comments_set(bool preserve)
787{
788 cf_preserve_comments = preserve;
789}
790
791/*
792 * Private getter declared in cf_priv.h for cf_file.c's parser hook.
793 * Keeps cf_preserve_comments truly private to cf_util.c; the public
794 * API is the setter.
795 */
797{
799}
800
801/*
802 * On by default - the runtime parser always wants `${foo}` resolved
803 * to the value of `foo`. Tools like radjson2conf, which build a
804 * tree from JSON and write it back out, flip this off so values
805 * containing `${...}` round-trip verbatim instead of being resolved
806 * against an incomplete fragment tree. $INCLUDE is a separate code
807 * path and is unaffected.
808 */
809static bool cf_expand_vars = true;
810
811void cf_expand_variables_set(bool expand)
812{
813 cf_expand_vars = expand;
814}
815
817{
818 return cf_expand_vars;
819}
820
822{
823 CONF_COMMENT *c;
824
825 if (!parent) return NULL;
826
827 c = talloc_zero(parent, CONF_COMMENT);
828 if (!c) return NULL;
829
831 cf_section_to_item(parent), NULL, 0);
832
833 c->text = text ? talloc_strdup(c, text) : NULL;
834
835 /*
836 * Append to the parent's ordered children list, but do NOT
837 * insert into ident1 / ident2 trees - comments aren't
838 * name-keyed and shouldn't show up in cf_pair_find / cf_section_find.
839 */
840 fr_dlist_insert_tail(&parent->item.children, &c->item);
841 return c;
842}
843
844/** Free a section and associated trees
845 *
846 * @param[in] cs to free.
847 * @return 0
848 */
850{
851 if (cs->item.ident1) TALLOC_FREE(cs->item.ident1);
852 if (cs->item.ident2) TALLOC_FREE(cs->item.ident2);
853
854 return 0;
855}
856
857/** Allocate a #CONF_SECTION
858 *
859 * @param[in] ctx to allocate
860 * @param[in] parent #CONF_SECTION to hang this #CONF_SECTION off of.
861 * If parent is not NULL, the new section will be added as a child.
862 * @param[in] name1 Primary name.
863 * @param[in] name2 Secondary name.
864 * @param[in] filename Caller file name for debugging. May be overridden later.
865 * @param[in] lineno Caller line number for debugging. May be overridden later.
866 * @return
867 * - NULL on error.
868 * - A new #CONF_SECTION parented by parent.
869 */
871 char const *name1, char const *name2,
872 char const *filename, int lineno)
873{
874 CONF_SECTION *cs;
875 char buffer[1024];
876
877 if (!name1) return NULL;
878
879 if (name2 && parent) {
880 char const *p;
881
882 p = strchr(name2, '$');
883 if (p && (p[1] != '{')) p = NULL;
884
885 if (p) {
886 name2 = cf_expand_variables(parent->item.filename,
887 parent->item.lineno,
888 parent,
889 buffer, sizeof(buffer), name2, -1, NULL, false);
890
891 if (!name2) {
892 ERROR("Failed expanding section name");
893 return NULL;
894 }
895 }
896 }
897
898 cs = talloc_zero(ctx, CONF_SECTION);
899 if (!cs) return NULL;
900
902
903 MEM(cs->name1 = talloc_strdup(cs, name1));
904 if (name2) {
905 MEM(cs->name2 = talloc_strdup(cs, name2));
907 }
908 talloc_set_destructor(cs, _cf_section_free);
909
910 if (parent) {
911 CONF_DATA const *cd;
912 conf_parser_t *rule;
913
914 /*
915 * Look up the parents parsing rules for itself.
916 * If there are rules, then one of them might be
917 * parsing rules for this new child. If that
918 * happens, we push the child parsing rules to
919 * this new child.
920 */
922 if (cd) {
923 rule = cf_data_value(cd);
924
925 if ((rule->flags & CONF_FLAG_SUBSECTION) &&
926 rule->on_read && rule->subcs) {
927 conf_parser_t const *rule_p;
928
929 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
930 if ((rule_p->flags & CONF_FLAG_SUBSECTION) &&
931 rule_p->on_read &&
932 (strcmp(rule_p->name1, name1) == 0)) {
933 if (_cf_section_rule_push(cs, rule_p,
934 cd->item.filename, cd->item.lineno) < 0) {
935 error:
936 talloc_free(cs);
937 return NULL;
938 }
939
940 if (rule_p->on_read(ctx, NULL, NULL,
941 cf_section_to_item(cs), rule_p) < 0) goto error;
942 goto done;
943 }
944 }
945 }
946 }
947
948 /*
949 * Or, the parent may already have parse rules
950 * for this new child. In which case we push the
951 * child rules for this section, and then do the
952 * on_read callback.
953 */
955 if (cd) {
956 rule = cf_data_value(cd);
957 if ((rule->flags & CONF_FLAG_SUBSECTION) &&
958 rule->on_read) {
959 if (cf_section_rules_push(cs, rule->subcs) < 0) goto error;
960 if (rule->on_read(ctx, NULL, NULL, cf_section_to_item(cs), rule) < 0) goto error;
961 }
962 }
963
964 done:
965 cs->depth = parent->depth + 1;
966 if (cf_item_add(parent, &(cs->item)) < 0) goto error;
967 }
968
969 return cs;
970}
971
972/** Set the filename of a #CONF_ITEM
973 *
974 * @param[in] ci to set filename on.
975 * @param[in] filename to set.
976 */
977void _cf_filename_set(CONF_ITEM *ci, char const *filename)
978{
980
981 ci->filename = talloc_strdup(ci, filename);
982}
983
984/** Set the line number of a #CONF_ITEM
985 *
986 * @param[in] ci to set the lineno for.
987 * @param[in] lineno to set.
988 */
989void _cf_lineno_set(CONF_ITEM *ci, int lineno)
990{
991 ci->lineno = lineno;
992}
993
994/** Count the items in a section, giving up once the count reaches a limit
995 *
996 * `total` is the running count, shared by every level of the walk. Each
997 * level adds its own children to it, so the caller reads the whole subtree
998 * from one variable rather than from a return value which each level would
999 * have to add up by hand.
1000 *
1001 * Stopping early is what keeps this cheap. The answer only has to be good
1002 * enough to compare against the limit, so the walk never costs more than the
1003 * limit itself, however large the section is.
1004 *
1005 * @param[in] cs to count, including everything nested inside it. NULL
1006 * counts as nothing, because cf_section_dup() is called
1007 * with a NULL parent.
1008 * @param[in,out] total the running count, which the caller sets to 0.
1009 * @return `*total`, so that a caller which wants only the answer can take it
1010 * from here.
1011 */
1012static unsigned int cf_section_item_count(CONF_SECTION const *cs, unsigned int *total)
1013{
1014 CONF_ITEM const *ci = NULL;
1015
1016 if (!cs || !total) return 0;
1017
1018 /*
1019 * Every item at this level counts, and the list knows how many
1020 * there are without being walked. Only the sections need
1021 * walking, for what is nested inside them.
1022 */
1023 *total += fr_dlist_num_elements(&cs->item.children);
1024 if (*total >= CF_SECTION_MAX_DUP_ITEMS) return *total;
1025
1026 while ((ci = fr_dlist_next(&cs->item.children, ci)) != NULL) {
1027 if (ci->type != CONF_ITEM_SECTION) continue;
1028
1029 if (cf_section_item_count(cf_item_to_section(ci), total) >= CF_SECTION_MAX_DUP_ITEMS) return *total;
1030 }
1031
1032 return *total;
1033}
1034
1035/** Duplicate a configuration section
1036 *
1037 * @note recursively duplicates any child sections.
1038 * @note does not duplicate any data associated with a section, or its child sections.
1039 *
1040 * @param[in] ctx to allocate memory in.
1041 * @param[in] parent section (may be NULL).
1042 * @param[in] cs to duplicate.
1043 * @param[in] name1 of new section.
1044 * @param[in] name2 of new section.
1045 * @param[in] copy_meta Copy additional meta data for a section
1046 * (like template, base, depth, parsed state,
1047 * and variables).
1048 * @return
1049 * - A duplicate of the existing section.
1050 * - NULL on error.
1051 */
1053 char const *name1, char const *name2, bool copy_meta)
1054{
1055 CONF_SECTION *out, *dst;
1056 CONF_SECTION const *src;
1057 CONF_ITEM const *ci;
1058 unsigned int parent_count = 0, cs_count = 0;
1059
1060 /*
1061 * The destination can't be inside of the source. Otherwise the copy is added to the source, and
1062 * then the loop below copies the copy, forever.
1063 */
1064 for (ci = parent ? &parent->item : NULL; ci != NULL; ci = ci->parent) {
1065 if (ci != &cs->item) continue;
1066
1067 ERROR("%s[%d]: Cannot copy section %s into itself",
1068 cs->item.filename, cs->item.lineno, name1);
1069 return NULL;
1070 }
1071
1072 /*
1073 * Disallow exponential explosion. See the definition of CF_SECTION_MAX_DUP_ITEMS
1074 */
1075 (void) cf_section_item_count(parent, &parent_count);
1076 (void) cf_section_item_count(cs, &cs_count);
1077
1078 if ((parent_count + cs_count) >= CF_SECTION_MAX_DUP_ITEMS) {
1079 ERROR("%s[%d]: Copying section %s would create more than %u items in one section. "
1080 "There is likely some structural issue with the configuration files",
1082 return NULL;
1083 }
1084
1085 /*
1086 * Create the new output section.
1087 */
1088 MEM(out = cf_section_alloc(ctx, parent, name1, name2));
1089
1090 if (copy_meta) {
1091 out->template = cs->template;
1092 out->base = cs->base;
1093 out->depth = cs->depth;
1094 }
1095
1098
1099 /*
1100 * Start copying children of the input.
1101 */
1102 src = cs;
1103 ci = NULL;
1104 dst = out;
1105
1106 /*
1107 * Do this iteratively, because it's nicer than using the C stack.
1108 */
1109 while (true) {
1110 CONF_SECTION *src_child, *dst_child;
1111 CONF_PAIR *cp;
1112
1113 /*
1114 * Go to the next child. If there is none, then try to go back up to the parent.
1115 */
1116 ci = fr_dlist_next(&src->item.children, ci);
1117 if (!ci) {
1118 /*
1119 * We're back at the top, and we have no more children. We can stop looping.
1120 */
1121 if (src == cs) break;
1122
1123 /*
1124 * The current child is what we were just copying. The parent is now the childs
1125 * parent.
1126 */
1127 ci = &src->item;
1128 src = cf_item_to_section(src->item.parent);
1129 dst = cf_item_to_section(dst->item.parent);
1130 continue;
1131 }
1132
1133 fr_assert(ci != cf_section_to_item(cs));
1135
1136 switch (ci->type) {
1137 case CONF_ITEM_SECTION:
1138 src_child = cf_item_to_section(ci);
1139 dst_child = cf_section_alloc(dst, dst, src_child->name1, src_child->name2);
1140 if (!dst_child) {
1141 oom:
1143 return NULL;
1144 }
1145
1146 if (copy_meta) {
1147 dst_child->template = src_child->template;
1148 dst_child->base = src_child->base;
1149 dst_child->depth = src_child->depth;
1150 }
1151
1152 dst_child->item.filename = src_child->item.filename;
1153 dst_child->item.lineno = src_child->item.lineno;
1154
1155 /*
1156 * Descend into the child so its children get copied too.
1157 */
1158 src = src_child;
1159 dst = dst_child;
1160 ci = NULL;
1161 continue;
1162
1163 case CONF_ITEM_PAIR:
1164 cp = cf_pair_dup(dst, cf_item_to_pair(ci), copy_meta);
1165 if (!cp) goto oom;
1166 break;
1167
1168 case CONF_ITEM_DATA: /* Skip data */
1169 break;
1170
1171 case CONF_ITEM_COMMENT:
1172 /*
1173 * Preserve comment lines when duplicating a section -
1174 * it costs almost nothing and round-tripping utilities
1175 * stay correct.
1176 */
1177 {
1178 CONF_COMMENT const *src_co = cf_item_to_comment(ci);
1179 CONF_COMMENT *dst_co = cf_comment_alloc(dst, src_co->text);
1180
1181 if (!dst_co) goto oom;
1182
1183 cf_filename_set(dst_co, src_co->item.filename);
1184 cf_lineno_set(dst_co, src_co->item.lineno);
1185 }
1186 break;
1187
1188 case CONF_ITEM_INVALID:
1189 fr_assert(0);
1190 }
1191 }
1192
1193 return out;
1194}
1195
1196/** Return the first child in a CONF_SECTION
1197 *
1198 * @param[in] cs to return children from.
1199 * @return
1200 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
1201 * - NULL if no #CONF_ITEM matches that criteria.
1202 */
1207
1208/** Return the next child that's a #CONF_SECTION
1209 *
1210 * @param[in] cs to return children from.
1211 * @param[in] curr child to start searching from.
1212 * @return
1213 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
1214 * - NULL if no #CONF_ITEM matches that criteria.
1215 */
1220
1221/** Return the previous child that's a #CONF_SECTION
1222 *
1223 * @param[in] cs to return children from.
1224 * @param[in] curr child to start searching from.
1225 * @return
1226 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
1227 * - NULL if no #CONF_ITEM matches that criteria.
1228 */
1233
1234/** Find a CONF_SECTION with name1 and optionally name2.
1235 *
1236 * @param[in] cs The section we're searching in.
1237 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1238 * can be used to match any name1 value.
1239 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1240 * can be used to match any name2 value.
1241 * @return
1242 * - The first matching subsection.
1243 * - NULL if no subsections match.
1244 *
1245 * @hidecallergraph
1246 */
1248 char const *name1, char const *name2)
1249{
1251}
1252
1253/** Return the next matching section
1254 *
1255 * @param[in] cs The section we're searching in.
1256 * @param[in] prev section we found. May be NULL in which case
1257 * we just return the next section after prev.
1258 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1259 * can be used to match any name1 value.
1260 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1261 * can be used to match any name2 value.
1262 * @return
1263 * - The next CONF_SECTION.
1264 * - NULL if there are no more CONF_SECTIONs
1265 *
1266 * @hidecallergraph
1267 */
1269 char const *name1, char const *name2)
1270{
1272 CONF_ITEM_SECTION, name1, name2));
1273}
1274
1275/** Find an ancestor of the passed CONF_ITEM which has a child matching a specific name1 and optionally name2.
1276 *
1277 * @note Despite the name, this function also searches in ci for a matching item.
1278 *
1279 * Will walk up the configuration tree, searching in each parent until a matching section is found or
1280 * we hit the root.
1281 *
1282 * @param[in] ci The conf item we're searching back from.
1283 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1284 * can be used to match any name1 value.
1285 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1286 * can be used to match any name2 value.
1287 * @return
1288 * - The first matching subsection.
1289 * - NULL if no subsections match.
1290 */
1292 char const *name1, char const *name2)
1293{
1294 do {
1295 CONF_ITEM *found;
1296
1297 found = cf_find(ci, CONF_ITEM_SECTION, name1, name2);
1298 if (found) return cf_item_to_section(found);
1299 } while ((ci = cf_parent(ci)));
1300
1301 return NULL;
1302}
1303
1304/** Find a parent CONF_SECTION with name1 and optionally name2.
1305 *
1306 * @param[in] ci The section we're searching in.
1307 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1308 * can be used to match any name1 value.
1309 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1310 * can be used to match any name2 value.
1311 * @return
1312 * - The first matching subsection.
1313 * - NULL if no subsections match.
1314 */
1316 char const *name1, char const *name2)
1317{
1318 while ((ci = cf_parent(ci))) {
1319 CONF_SECTION *found;
1320
1321 if (!cf_item_is_section(ci)) continue; /* Could be data hanging off a pair*/
1322
1323 found = cf_item_to_section(ci);
1324
1325 if (cf_section_name_cmp(found, name1, name2) == 0) return found;
1326 }
1327
1328 return NULL;
1329}
1330
1331/** Find a pair in a #CONF_SECTION
1332 *
1333 * @param[in] cs the #CONF_SECTION to search in.
1334 * @param[in] attr to search for.
1335 * @return
1336 * - NULL if no pair can be found.
1337 * - The value of the pair found.
1338 */
1339char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr)
1340{
1341 CONF_PAIR *cp;
1342
1343 cp = cf_pair_find(cs, attr);
1344
1345 return (cp ? cp->value : NULL);
1346}
1347
1348/** Check if a given section matches the specified name1/name2 identifiers
1349 *
1350 * @param[in] cs to check.
1351 * @param[in] name1 identifier. May be CF_IDENT_ANY for wildcard matches.
1352 * @param[in] name2 identifier. May be CF_IDENT_ANY for wildcard matches.
1353 * @return
1354 * - >1 if cs is greater than the identifiers.
1355 * - 0 if cs matches the identifiers.
1356 * - <0 if cs is less than the identifiers.
1357 */
1358fr_cmp_ret_t cf_section_name_cmp(CONF_SECTION const *cs, char const *name1, char const *name2)
1359{
1360 fr_cmp_ret_t ret;
1361
1362 if (name1 != CF_IDENT_ANY) {
1363 ret = CMP(strcmp(cf_section_name1(cs), name1), 0);
1364 if (ret != 0) return ret;
1365 }
1366
1367 if (name2 != CF_IDENT_ANY) {
1368 char const *cs_name2 = cf_section_name2(cs);
1369
1370 if (!cs_name2) {
1371 if (!name2) return CMP_EQ;
1372 return CMP_GT;
1373 }
1374 if (!name2) return CMP_LT;
1375
1376 return CMP(strcmp(cs_name2, name2), 0);
1377 }
1378
1379 return CMP_EQ;
1380}
1381
1382/** Return the first identifier of a #CONF_SECTION
1383 *
1384 * @param[in] cs to return identifiers for.
1385 * @return
1386 * - The first identifier.
1387 * - NULL if cs was NULL or no name1 set.
1388 *
1389 * @hidecallergraph
1390 */
1391char const *cf_section_name1(CONF_SECTION const *cs)
1392{
1393 return (cs ? cs->name1 : NULL);
1394}
1395
1396/** Return the second identifier of a #CONF_SECTION
1397 *
1398 * @param[in] cs to return identifiers for.
1399 * @return
1400 * - The second identifier.
1401 * - NULL if cs was NULL or no name2 set.
1402 *
1403 * @hidecallergraph
1404 */
1405char const *cf_section_name2(CONF_SECTION const *cs)
1406{
1407 return (cs ? cs->name2 : NULL);
1408}
1409
1410/** Return name2 if set, else name1
1411 *
1412 * @param[in] cs to return identifiers for.
1413 * @return name1 or name2 identifier.
1414 *
1415 * @hidecallergraph
1416 */
1417char const *cf_section_name(CONF_SECTION const *cs)
1418{
1419 char const *name;
1420
1421 name = cf_section_name2(cs);
1422 if (name) return name;
1423
1424 return cf_section_name1(cs);
1425}
1426
1427/** Return variadic argument at the specified index
1428 *
1429 * @param[in] cs containing the arguments.
1430 * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1431 * @return the argument value or NULL.
1432 */
1433char const *cf_section_argv(CONF_SECTION const *cs, int argc)
1434{
1435 if (!cs || !cs->argv || (argc < 0) || (argc >= cs->argc)) return NULL;
1436
1437 return cs->argv[argc];
1438}
1439
1440/** Return the quoting of the name2 identifier
1441 *
1442 * @param[in] cs containing name2.
1443 * @return
1444 * - #T_BARE_WORD.
1445 * - #T_SINGLE_QUOTED_STRING.
1446 * - #T_BACK_QUOTED_STRING.
1447 * - #T_DOUBLE_QUOTED_STRING.
1448 * - #T_INVALID if cs was NULL.
1449 */
1451{
1452 if (!cs) return T_INVALID;
1453
1454 return cs->name2_quote;
1455}
1456
1457/** Return the quoting for one of the variadic arguments
1458 *
1459 * @param[in] cs containing the arguments.
1460 * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1461 * @return
1462 * - #T_BARE_WORD.
1463 * - #T_SINGLE_QUOTED_STRING.
1464 * - #T_BACK_QUOTED_STRING.
1465 * - #T_DOUBLE_QUOTED_STRING.
1466 * - #T_INVALID if cs was NULL or the index was invalid.
1467 */
1469{
1470 if (!cs || !cs->argv_quote || (argc < 0) || (argc >= cs->argc)) return T_INVALID;
1471
1472 return cs->argv_quote[argc];
1473}
1474
1475/** Allocate a #CONF_PAIR
1476 *
1477 * @param[in] parent #CONF_SECTION to hang this #CONF_PAIR off of.
1478 * @param[in] attr name.
1479 * @param[in] value of #CONF_PAIR.
1480 * @param[in] op #T_OP_EQ, #T_OP_SET etc.
1481 * @param[in] lhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1482 * @param[in] rhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1483 * @return
1484 * - NULL on error.
1485 * - A new #CONF_SECTION parented by parent.
1486 */
1487CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value,
1488 fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
1489{
1490 CONF_PAIR *cp;
1491
1493 if (!attr) return NULL;
1494
1495 cp = talloc_zero(parent, CONF_PAIR);
1496 if (!cp) return NULL;
1497
1499
1500 cp->lhs_quote = lhs_quote;
1501 cp->rhs_quote = rhs_quote;
1502 cp->op = op;
1503
1504 cp->attr = talloc_strdup(cp, attr);
1505 if (!cp->attr) {
1506 error:
1507 talloc_free(cp);
1508 return NULL;
1509 }
1510
1511 if (value) {
1512 cp->value = talloc_strdup(cp, value);
1513 if (!cp->value) goto error;
1514 }
1515
1516 if (parent && (cf_item_add(parent, &(cp->item)) < 0)) goto error;
1517 return cp;
1518}
1519
1520/** Duplicate a #CONF_PAIR
1521 *
1522 * @param parent to allocate new pair in.
1523 * @param cp to duplicate.
1524 * @param copy_meta Copy additional meta data for a pair
1525 * @return
1526 * - NULL on error.
1527 * - A duplicate of the input pair.
1528 */
1530{
1531 CONF_PAIR *new;
1532
1534 fr_assert(cp);
1535
1536 new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), cp->op, cp->lhs_quote, cp->rhs_quote);
1537 if (!new) return NULL;
1538
1539 if (copy_meta) {
1540 new->item.parsed = cp->item.parsed;
1541 new->item.referenced = cp->item.referenced;
1542 }
1543 cf_lineno_set(new, cp->item.lineno);
1544 cf_filename_set(new, cp->item.filename);
1545
1546 return new;
1547}
1548
1549/** Replace pair value in a given section with the given value.
1550 *
1551 * @note A new pair with the same metadata as the #CONF_PAIR will be added
1552 * even if the #CONF_PAIR can't be found inside the #CONF_SECTION.
1553 *
1554 * @param[in] cs to replace pair in.
1555 * @param[in] cp to replace.
1556 * @param[in] value New value to assign to cp.
1557 * @return
1558 * - 0 on success.
1559 * - -1 on failure.
1560 */
1562{
1563 if (!cs || !cp || !value) return -1;
1564
1566
1567 MEM(cp->value = talloc_strdup(cp, value));
1568
1569 return 0;
1570}
1571
1572
1573/** Mark an item as parsed
1574 *
1575 * @param[in] ci to mark as parsed.
1576 */
1578{
1579 ci->parsed = true;
1580}
1581
1582/** Return whether an item has already been parsed
1583 *
1584 * @param[in] ci to check.
1585 * @return
1586 * - true if item has been parsed.
1587 * - false if the pair hasn't been parsed.
1588 */
1590{
1591 return ci->parsed;
1592}
1593
1594/** Return the first child that's a #CONF_PAIR
1595 *
1596 * @param[in] cs to return children from.
1597 * @return
1598 * - The first #CONF_ITEM that's a child of cs and a CONF_PAIR.
1599 * - NULL if no #CONF_ITEM matches that criteria.
1600 */
1605
1606/** Return the next child that's a #CONF_PAIR
1607 *
1608 * @param[in] cs to return children from.
1609 * @param[in] curr child to start searching from.
1610 * @return
1611 * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1612 * - NULL if no #CONF_ITEM matches that criteria.
1613 */
1618
1619/** Return the previous child that's a #CONF_PAIR
1620 *
1621 * @param[in] cs to return children from.
1622 * @param[in] curr child to start searching from.
1623 * @return
1624 * - The previous #CONF_ITEM that's a child of cs and a CONF_PAIR.
1625 * - NULL if no #CONF_ITEM matches that criteria.
1626 */
1631
1632/** Search for a #CONF_PAIR with a specific name
1633 *
1634 * @param[in] cs to search in.
1635 * @param[in] attr to find.
1636 * @return
1637 * - The next matching #CONF_PAIR.
1638 * - NULL if none matched.
1639 */
1640CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *attr)
1641{
1642 return cf_item_to_pair(cf_find(cf_section_to_item(cs), CONF_ITEM_PAIR, attr, NULL));
1643}
1644
1645/** Find a pair with a name matching attr, after specified pair
1646 *
1647 * @param[in] cs to search in.
1648 * @param[in] prev Pair to search from (may be NULL).
1649 * @param[in] attr to find (may be NULL in which case any attribute matches).
1650 * @return
1651 * - The next matching #CONF_PAIR
1652 * - NULL if none matched.
1653 */
1654CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
1655{
1657}
1658
1659/** Find a pair with a name matching attr in the specified section or one of its parents
1660 *
1661 * @param[in] cs to search in. Will start in the current section
1662 * and work upwards.
1663 * @param[in] attr to find.
1664 * @return
1665 * - A matching #CONF_PAIR.
1666 * - NULL if none matched.
1667 */
1668CONF_PAIR *cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
1669{
1670 CONF_ITEM const *parent = cf_section_to_item(cs);
1671
1672 do {
1673 CONF_ITEM *found;
1674
1675 found = cf_find(parent, CONF_ITEM_PAIR, attr, NULL);
1676 if (found) return cf_item_to_pair(found);
1677 } while ((parent = cf_parent(parent)));
1678
1679 return NULL;
1680}
1681
1682/** Callback to determine the number of pairs in a section
1683 *
1684 * @param[out] count Where we store the number of pairs found.
1685 * @param[in] cs we're currently searching in.
1686 */
1687static void _pair_count(int *count, CONF_SECTION const *cs)
1688{
1689 CONF_ITEM const *ci = NULL;
1690
1691 while ((ci = cf_item_next(cs, ci))) {
1692 if (cf_item_is_section(ci)) {
1694 continue;
1695 }
1696
1697 (*count)++;
1698 }
1699}
1700
1701/** Count the number of conf pairs beneath a section
1702 *
1703 * @param[in] cs to search for items in.
1704 * @return The number of pairs nested within section.
1705 */
1707{
1708 int count = 0;
1709
1710 _pair_count(&count, cs);
1711
1712 return count;
1713}
1714
1715/** Count the number of times an attribute occurs in a parent section
1716 *
1717 * @param[in] cs to search for items in.
1718 * @param[in] attr to search for.
1719 * @return The number of pairs of that attribute type.
1720 */
1721unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
1722{
1723 size_t i;
1724 CONF_PAIR *cp = NULL;
1725
1726 for (i = 0; (cp = cf_pair_find_next(cs, cp, attr)); i++);
1727
1728 return i;
1729}
1730
1731/** Return the attr of a #CONF_PAIR
1732 *
1733 * Return the LHS value of a pair (the attribute).
1734 *
1735 * @param[in] pair to return the attribute for.
1736 * @return
1737 * - NULL if the pair was NULL.
1738 * - The attribute name of the pair.
1739 *
1740 * @hidecallergraph
1741 */
1742char const *cf_pair_attr(CONF_PAIR const *pair)
1743{
1744 return (pair ? pair->attr : NULL);
1745}
1746
1747/** Return the value of a #CONF_PAIR
1748 *
1749 * Return the RHS value of a pair (the value).
1750 *
1751 * @param[in] pair to return the value of.
1752 * @return
1753 * - NULL if pair was NULL or the pair has no value.
1754 * - The string value of the pair.
1755 *
1756 * @hidecallergraph
1757 */
1758char const *cf_pair_value(CONF_PAIR const *pair)
1759{
1760 return (pair ? pair->value : NULL);
1761}
1762
1763/** Return the operator of a pair
1764 *
1765 * @param[in] pair to return the operator of.
1766 * @return
1767 * - T_INVALID if pair was NULL.
1768 * - T_OP_* (one of the operator constants).
1769 *
1770 * @hidecallergraph
1771 */
1773{
1774 return (pair ? pair->op : T_INVALID);
1775}
1776
1777/** Return the value (lhs) quoting of a pair
1778 *
1779 * @param pair to extract value type from.
1780 * @return
1781 * - #T_BARE_WORD.
1782 * - #T_SINGLE_QUOTED_STRING.
1783 * - #T_BACK_QUOTED_STRING.
1784 * - #T_DOUBLE_QUOTED_STRING.
1785 * - #T_INVALID if the pair is NULL.
1786 */
1788{
1789 return (pair ? pair->lhs_quote : T_INVALID);
1790}
1791
1792/** Return the value (rhs) quoting of a pair
1793 *
1794 * @param pair to extract value type from.
1795 * @return
1796 * - #T_BARE_WORD.
1797 * - #T_SINGLE_QUOTED_STRING.
1798 * - #T_BACK_QUOTED_STRING.
1799 * - #T_DOUBLE_QUOTED_STRING.
1800 * - #T_INVALID if the pair is NULL.
1801 */
1803{
1804 return (pair ? pair->rhs_quote : T_INVALID);
1805}
1806
1807/** Free user data associated with #CONF_DATA
1808 *
1809 * @param[in] cd being freed.
1810 * @return 0
1811 */
1812static int _cd_free(CONF_DATA *cd)
1813{
1814 return talloc_free(UNCONST(void *, cd->data));
1815}
1816
1817/** Allocate a new user data container
1818 *
1819 * @param[in] parent #CONF_PAIR, or #CONF_SECTION to hang CONF_DATA off of.
1820 * @param[in] data being added.
1821 * @param[in] type of data being added.
1822 * @param[in] name String identifier of the user data.
1823 * @param[in] do_free function, called when the parent #CONF_SECTION is being freed.
1824 * @return
1825 * - CONF_DATA on success.
1826 * - NULL on error.
1827 */
1828static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
1829{
1830 CONF_DATA *cd;
1831
1832 cd = talloc_zero(parent, CONF_DATA);
1833 if (!cd) return NULL;
1834
1836
1837 /*
1838 * strdup so if the data is freed, we can
1839 * still remove it from the section without
1840 * explosions.
1841 */
1842 if (data) {
1843 cd->type = talloc_strdup(cd, type);
1844 cd->data = data;
1845 }
1846 if (name) cd->name = talloc_strdup(cd, name);
1847
1848 if (do_free) talloc_set_destructor(cd, _cd_free);
1849
1850 if (cf_item_add(parent, cd) < 0) {
1851 talloc_free(cd);
1852 return NULL;
1853 }
1854
1855 return cd;
1856}
1857
1858/** Find user data in a config section
1859 *
1860 * @param[in] ci The section to search for data in.
1861 * @param[in] type of user data. Used for name spacing and walking over a specific
1862 * type of user data.
1863 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1864 * may be used to match on type only.
1865 * @return
1866 * - The user data.
1867 * - NULL if no user data exists.
1868 */
1869CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
1870{
1872}
1873
1874/** Return the next item of user data
1875 *
1876 * @param[in] ci The section to search for data in.
1877 * @param[in] prev section we found. May be NULL in which case
1878 * we just return the next section after prev.
1879 * @param[in] type of user data. Used for name spacing and walking over a specific
1880 * type of user data.
1881 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1882 * can be used to match any name2 value.
1883 * @return
1884 * - The next matching #CONF_DATA.
1885 * - NULL if there is no more matching #CONF_DATA.
1886 */
1887CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
1888{
1890}
1891
1892/** Find matching data in the specified section or one of its parents
1893 *
1894 * @param[in] ci The section to search for data in.
1895 * @param[in] type of user data. Used for name spacing and walking over a specific
1896 * type of user data.
1897 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1898 * may be used to match on type only.
1899 * @return
1900 * - The next matching #CONF_DATA.
1901 * - NULL if there is no more matching #CONF_DATA.
1902 */
1903CONF_DATA *_cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
1904{
1905 CONF_ITEM const *parent = ci;
1906
1907 do {
1908 CONF_ITEM *found;
1909
1911 if (found) return cf_item_to_data(found);
1912 } while ((parent = cf_parent(parent)));
1913
1914 return NULL;
1915}
1916
1917/** Return the user assigned value of #CONF_DATA
1918 *
1919 * @param[in] cd to return value of.
1920 * @return the user data stored within the #CONF_DATA.
1921 */
1922void *cf_data_value(CONF_DATA const *cd)
1923{
1924 void *to_return;
1925
1926 if (!cd) return NULL;
1927
1928 memcpy(&to_return, &cd->data, sizeof(to_return));
1929
1930 return to_return;
1931}
1932
1933/** Add talloced user data to a config section
1934 *
1935 * @param[in] ci to add data to.
1936 * @param[in] data to add.
1937 * @param[in] name String identifier of the user data.
1938 * @param[in] do_free Function to free user data when the CONF_SECTION is freed.
1939 * @param[in] filename Source file the #CONF_DATA was added in.
1940 * @param[in] lineno the #CONF_DATA was added at.
1941 * @return
1942 * - #CONF_DATA - opaque handle to the stored data - on success.
1943 * - NULL error.
1944 */
1945CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free,
1946 char const *filename, int lineno)
1947{
1948 CONF_DATA *cd;
1949 CONF_DATA const *found;
1950 char const *type = NULL;
1951
1952 if (!ci) return NULL;
1953
1954 if (data) type = talloc_get_name(data);
1955
1956 /*
1957 * Already exists. Can't add it.
1958 */
1959 found = _cf_data_find(ci, type, name);
1960 if (found) {
1961 return NULL;
1962 }
1963
1964 cd = cf_data_alloc(ci, data, type, name, do_free);
1965 if (!cd) {
1966 cf_log_err(ci, "Failed allocating data");
1967 return NULL;
1968 }
1969 cd->is_talloced = true;
1970 cf_filename_set(cd, filename);
1971 cf_lineno_set(cd, lineno);
1972
1973 return cd;
1974}
1975
1976/** Add non-talloced user data to a config section
1977 *
1978 * @param[in] ci to add data to.
1979 * @param[in] data to add.
1980 * @param[in] type identifier of the user data.
1981 * @param[in] name String identifier of the user data.
1982 * @param[in] filename Source file the #CONF_DATA was added in.
1983 * @param[in] lineno the #CONF_DATA was added at.
1984 * - #CONF_DATA - opaque handle to the stored data - on success.
1985 * - NULL error.
1986 */
1987CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name,
1988 char const *filename, int lineno)
1989{
1990 CONF_DATA *cd;
1991 CONF_DATA const *found;
1992
1993 /*
1994 * Already exists. Can't add it.
1995 */
1996 found = _cf_data_find(ci, type, name);
1997 if (found) {
1998 /*
1999 * Suppress these, as it's OK for the conf_parser_t in main_config.c
2000 */
2001 if (strcmp(type, "conf_parser_t") == 0) return NULL;
2002
2003 cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type,
2004 name, found->item.filename, found->item.lineno);
2005 return NULL;
2006 }
2007
2008 cd = cf_data_alloc(ci, data, type, name, false);
2009 if (!cd) {
2010 cf_log_err(ci, "Failed allocating data");
2011 return NULL;
2012 }
2013 cd->is_talloced = false;
2014 cf_filename_set(cd, filename);
2015 cf_lineno_set(cd, lineno);
2016
2017 return cd;
2018}
2019
2020/** Remove data from a configuration section
2021 *
2022 * @note If cd was not found it will not be freed, and it is the caller's responsibility
2023 * to free it explicitly, or free the section it belongs to.
2024 *
2025 * @param[in] parent to remove data from.
2026 * @param[in] cd opaque handle of the stored data.
2027 * @return
2028 * - The value stored within the data (if cd is valid and was found and removed).
2029 * - NULL if not found.
2030 */
2032{
2033 void *data;
2034
2035 if (!cd) return NULL;
2036
2037 (void)cf_item_remove(parent, cd);
2038
2039 talloc_set_destructor(cd, NULL); /* Disarm the destructor */
2040 memcpy(&data, &cd->data, sizeof(data));
2042
2043 return data;
2044}
2045
2046/** Walk over a specific type of CONF_DATA
2047 *
2048 * @param[in] ci containing the CONF_DATA to walk over.
2049 * @param[in] type of CONF_DATA to walk over.
2050 * @param[in] cb to call when we find CONF_DATA of the specified type.
2051 * @param[in] ctx to pass to cb.
2052 * @return
2053 * - 0 on success.
2054 * - -1 on failure.
2055 */
2056int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
2057{
2058 CONF_DATA *cd;
2059 CONF_ITEM *item;
2060 fr_rb_tree_t *tree;
2062 int ret = 0;
2063
2064 if (!ci->ident2) return 0;
2065
2066 tree = ci->ident2;
2067
2068 for (item = fr_rb_iter_init_inorder(tree, &iter);
2069 item;
2070 item = fr_rb_iter_next_inorder(tree, &iter)) {
2071 /*
2072 * We're walking ident2, not all of the items will be data
2073 */
2074 if (item->type != CONF_ITEM_DATA) continue;
2075
2076 cd = (void *) item;
2077 if ((cd->type != type) && (strcmp(cd->type, type) != 0)) continue;
2078
2079 ret = cb(UNCONST(void *, cd->data), ctx);
2080 if (ret) {
2081 break;
2082 }
2083 }
2084
2085 return ret;
2086}
2087
2088static inline CC_HINT(nonnull) void truncate_filename(char const **e, char const **p, int *len, char const *filename)
2089{
2090 size_t flen;
2091 char const *q;
2092
2093 #define FILENAME_TRUNCATE 60
2094
2095 *p = filename;
2096 *e = "";
2097
2098 flen = talloc_strlen(filename);
2099 if (flen <= FILENAME_TRUNCATE) {
2100 *len = (int)flen;
2101 return;
2102 }
2103
2104 *p += flen - FILENAME_TRUNCATE;
2106
2107 q = strchr(*p, FR_DIR_SEP);
2108 if (q) {
2109 q++;
2110 *len -= (q - *p);
2111 *p += (q - *p);
2112 }
2113
2114 *e = "...";
2115}
2116
2117/** Check to see if the CONF_PAIR value is present in the specified table
2118 *
2119 * If it's not present, return an error and produce a helpful log message
2120 *
2121 * @param[out] out The result of parsing the pair value.
2122 * @param[in] table to look for string values in.
2123 * @param[in] table_len Length of the table.
2124 * @param[in] cp to parse.
2125 * @return
2126 * - 0 on success.
2127 * - -1 on failure.
2128 */
2129int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
2130{
2131 char *list = NULL;
2132 int32_t res;
2133 size_t i;
2134
2136 if (res != FR_TABLE_NOT_FOUND) {
2137 *out = res;
2138 return 0;
2139 }
2140
2141 for (i = 0; i < table_len; i++) MEM(list = talloc_asprintf_append_buffer(list, "'%s', ", table[i].name.str));
2142
2143 if (!list) {
2144 cf_log_err(cp, "Internal error parsing %s: Table was empty", cf_pair_attr(cp));
2145 return -1;
2146 }
2147
2148 /*
2149 * Trim the final ", "
2150 */
2151 MEM(list = talloc_bstr_realloc(NULL, list, talloc_array_length(list) - 2));
2152
2153 cf_log_err(cp, "Invalid value \"%s\". Expected one of %s", cf_pair_value(cp), list);
2154
2155 talloc_free(list);
2156
2157 return -1;
2158}
2159
2160/** Log an error message relating to a #CONF_ITEM
2161 *
2162 * @param[in] type of log message.
2163 * @param[in] ci #CONF_ITEM to print file/lineno for.
2164 * @param[in] file src file the log message was generated in.
2165 * @param[in] line number the log message was generated on.
2166 * @param[in] fmt of the message.
2167 * @param[in] ap Message args.
2168 */
2169void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
2170{
2171 va_list aq;
2172
2173 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2174
2175 if (!ci || !ci->filename || !*ci->filename || (*ci->filename == '<') ||
2176 (((type == L_DBG) || (type == L_INFO)) && !DEBUG_ENABLED4)) {
2177 va_copy(aq, ap);
2179 va_end(aq);
2180 return;
2181 }
2182
2183 {
2184 char const *e, *p;
2185 int len;
2186 char *msg;
2187
2188 truncate_filename(&e, &p, &len, ci->filename);
2189
2190 va_copy(aq, ap);
2191 msg = fr_vasprintf(NULL, fmt, aq);
2192 va_end(aq);
2193
2194 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2196 }
2197}
2198
2199/** Log an error message relating to a #CONF_ITEM
2200 *
2201 * @param[in] type of log message.
2202 * @param[in] file src file the log message was generated in.
2203 * @param[in] line number the log message was generated on.
2204 * @param[in] ci #CONF_ITEM to print file/lineno for.
2205 * @param[in] fmt of the message.
2206 * @param[in] ... Message args.
2207 */
2208void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2209{
2210 va_list ap;
2211
2212 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2213
2214 va_start(ap, fmt);
2215 _cf_vlog(type, ci, file, line, fmt, ap);
2216 va_end(ap);
2217}
2218
2219/** Log an error message relating to a #CONF_ITEM
2220 *
2221 * Drains the fr_strerror() stack emitting one or more error messages.
2222 *
2223 * @param[in] type of log message.
2224 * @param[in] file src file the log message was generated in.
2225 * @param[in] line number the log message was generated on.
2226 * @param[in] ci #CONF_ITEM to print file/lineno for.
2227 * @param[in] f_rules Additional optional formatting controls.
2228 * @param[in] fmt of the message.
2229 * @param[in] ap Message args.
2230 */
2231void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2232 fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
2233{
2234 va_list aq;
2235
2236 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2237
2238 if (!ci || !ci->filename) {
2239 va_copy(aq, ap);
2240 fr_vlog_perror(LOG_DST, type, file, line, f_rules, fmt, aq);
2241 va_end(aq);
2242 return;
2243 }
2244
2245 {
2246 char const *e, *p;
2247 int len;
2248 char *prefix;
2249 TALLOC_CTX *thread_log_pool;
2250 TALLOC_CTX *pool;
2251 fr_log_perror_format_t our_f_rules;
2252
2253 if (f_rules) {
2254 our_f_rules = *f_rules;
2255 } else {
2256 our_f_rules = (fr_log_perror_format_t){};
2257 }
2258
2259 /*
2260 * Get some scratch space from the logging code
2261 */
2262 thread_log_pool = fr_log_pool_init();
2263 pool = talloc_new(thread_log_pool);
2264
2265 truncate_filename(&e, &p, &len, ci->filename);
2266
2267 /*
2268 * Create the file location string
2269 */
2270 prefix = fr_asprintf(pool, "%s%.*s[%d]: ", e, len, p, ci->lineno);
2271
2272 /*
2273 * Prepend it to an existing first prefix
2274 */
2275 if (f_rules && f_rules->first_prefix) {
2276 char *first;
2277
2278 first = talloc_bstrdup(pool, prefix);
2279 MEM(talloc_strndup_append_buffer(first, f_rules->first_prefix, SIZE_MAX));
2280
2281 our_f_rules.first_prefix = first;
2282 } else {
2283 our_f_rules.first_prefix = prefix;
2284 }
2285
2286 /*
2287 * Prepend it to an existing subsq prefix
2288 */
2289 if (f_rules && f_rules->subsq_prefix) {
2290 char *subsq;
2291
2292 subsq = talloc_bstrdup(pool, prefix);
2293 MEM(talloc_strndup_append_buffer(subsq, f_rules->subsq_prefix, SIZE_MAX));
2294
2295 our_f_rules.subsq_prefix = subsq;
2296 } else {
2297 our_f_rules.subsq_prefix = prefix;
2298 }
2299
2300 va_copy(aq, ap);
2301 fr_vlog_perror(LOG_DST, type, file, line, &our_f_rules, fmt, aq);
2302 va_end(aq);
2303
2304 talloc_free(pool);
2305 }
2306}
2307
2308/** Log an error message relating to a #CONF_ITEM
2309 *
2310 * Drains the fr_strerror() stack emitting one or more error messages.
2311 *
2312 * @param[in] type of log message.
2313 * @param[in] file src file the log message was generated in.
2314 * @param[in] line number the log message was generated on.
2315 * @param[in] ci #CONF_ITEM to print file/lineno for.
2316 * @param[in] f_rules Additional optional formatting controls.
2317 * @param[in] fmt of the message.
2318 * @param[in] ... Message args.
2319 */
2320void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2321 fr_log_perror_format_t const *f_rules, char const *fmt, ...)
2322{
2323 va_list ap;
2324
2325 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2326
2327 va_start(ap, fmt);
2328 _cf_vlog_perr(type, ci, file, line, f_rules, fmt, ap);
2329 va_end(ap);
2330}
2331
2332/** Log a debug message relating to a #CONF_ITEM
2333 *
2334 * Always emits a filename/lineno prefix if available
2335 *
2336 * @param[in] type of log message.
2337 * @param[in] file src file the log message was generated in.
2338 * @param[in] line number the log message was generated on.
2339 * @param[in] ci #CONF_ITEM to print file/lineno for.
2340 * @param[in] fmt of the message.
2341 * @param[in] ... Message args.
2342 */
2343void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2344{
2345 va_list ap;
2346
2347 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2348
2349 if (!ci || !ci->filename) {
2350 va_start(ap, fmt);
2351 fr_vlog(LOG_DST, type, file, line, fmt, ap);
2352 va_end(ap);
2353 return;
2354 }
2355
2356 {
2357 char const *e, *p;
2358 int len;
2359 char *msg;
2360
2361 truncate_filename(&e, &p, &len, ci->filename);
2362
2363 va_start(ap, fmt);
2364 msg = fr_vasprintf(NULL, fmt, ap);
2365 va_end(ap);
2366
2367 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2369 }
2370}
2371
2372/** Log an error message in the context of a child pair of the specified parent
2373 *
2374 * @param[in] parent containing the pair.
2375 * @param[in] child name to use as a logging context.
2376 * @param[in] type of log message.
2377 * @param[in] file src file the log message was generated in.
2378 * @param[in] line number the log message was generated on.
2379 * @param[in] fmt of the message.
2380 * @param[in] ... Message args.
2381 */
2383 char const *file, int line, char const *fmt, ...)
2384{
2385 va_list ap;
2386 CONF_PAIR const *cp;
2387
2388 cp = cf_pair_find(parent, child);
2389 if (cp) {
2390 va_start(ap, fmt);
2391 _cf_vlog(type, CF_TO_ITEM(cp), file, line, fmt, ap);
2392 va_end(ap);
2393 return;
2394 }
2395
2396 va_start(ap, fmt);
2398 va_end(ap);
2399}
2400
2401
2402/** Log an error message in the context of a child pair of the specified parent
2403 *
2404 * @param[in] parent containing the pair.
2405 * @param[in] child name to use as a logging context.
2406 * @param[in] type of log message.
2407 * @param[in] file src file the log message was generated in.
2408 * @param[in] line number the log message was generated on.
2409 * @param[in] f_rules Line prefixes.
2410 * @param[in] fmt of the message.
2411 * @param[in] ... Message args.
2412 */
2414 char const *file, int line, fr_log_perror_format_t const *f_rules,
2415 char const *fmt, ...)
2416{
2417 va_list ap;
2418 CONF_PAIR const *cp;
2419
2420 cp = cf_pair_find(parent, child);
2421 if (cp) {
2422 va_start(ap, fmt);
2423 _cf_vlog_perr(type, CF_TO_ITEM(cp), file, line, f_rules, fmt, ap);
2424 va_end(ap);
2425 return;
2426 }
2427
2428 va_start(ap, fmt);
2429 _cf_vlog_perr(type, CF_TO_ITEM(parent), file, line, f_rules, fmt, ap);
2430 va_end(ap);
2431}
2432
2433/** Print out debugging information about a CONFIG_ITEM
2434 *
2435 * @param[in] ci being debugged.
2436 */
2438{
2439 /*
2440 * Print summary of the item
2441 */
2442 switch (ci->type) {
2443 case CONF_ITEM_SECTION:
2444 {
2445 CONF_SECTION const *cs = cf_item_to_section(ci);
2446 int i;
2447
2448 DEBUG("SECTION - %p", cs);
2449 DEBUG(" name1 : %s", cs->name1);
2450 DEBUG(" name2 : %s", cs->name2 ? cs->name2 : "<none>");
2451 DEBUG(" name2_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cs->name2_quote, "<INVALID>"));
2452 DEBUG(" argc : %d", cs->argc);
2453
2454 for (i = 0; i < cs->argc; i++) {
2455 char const *quote = fr_table_str_by_value(fr_token_quotes_table, cs->argv_quote[i], "<INVALID>");
2456 DEBUG(" argv[%i] : %s%s%s", i, quote, cs->argv[i], quote);
2457 }
2458 }
2459 break;
2460
2461 case CONF_ITEM_PAIR:
2462 {
2463 CONF_PAIR const *cp = cf_item_to_pair(ci);
2464
2465 DEBUG("PAIR - %p", cp);
2466 DEBUG(" attr : %s", cp->attr);
2467 DEBUG(" value : %s", cp->value);
2468 DEBUG(" operator : %s", fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"));
2469 DEBUG(" lhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>"));
2470 DEBUG(" rhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>"));
2471 DEBUG(" pass2 : %s", cp->pass2 ? "yes" : "no");
2472 DEBUG(" parsed : %s", cp->item.parsed ? "yes" : "no");
2473 }
2474 break;
2475
2476 case CONF_ITEM_DATA:
2477 {
2478 CONF_DATA const *cd = cf_item_to_data(ci);
2479
2480 DEBUG("DATA - %p", cd);
2481 DEBUG(" type : %s", cd->type);
2482 DEBUG(" name : %s", cd->name);
2483 DEBUG(" data : %p", cd->data);
2484 }
2485 break;
2486
2487 default:
2488 DEBUG("INVALID - %p", ci);
2489 return;
2490 }
2491
2492 DEBUG(" filename : %s", ci->filename);
2493 DEBUG(" line : %i", ci->lineno);
2494 if (ci->parent) DEBUG(" next : %p", fr_dlist_next(&ci->parent->children, ci));
2495 DEBUG(" parent : %p", ci->parent);
2496 DEBUG(" children : %s", cf_item_has_no_children(ci) ? "no" : "yes");
2497 DEBUG(" ident1 tree : %p (%u entries)", ci->ident1, ci->ident1 ? fr_rb_num_elements(ci->ident1) : 0);
2498 DEBUG(" ident2 tree : %p (%u entries)", ci->ident2, ci->ident2 ? fr_rb_num_elements(ci->ident2) : 0);
2499
2500 if (cf_item_has_no_children(ci)) return;
2501
2502 /*
2503 * Print summary of the item's children
2504 */
2505 DEBUG("CHILDREN");
2506
2507 cf_item_foreach(ci, child) {
2508 char const *in_ident1, *in_ident2;
2509 CONF_ITEM *found;
2510
2511 fr_rb_find((void **)&found, ci->ident1, child);
2512 in_ident1 = found == child? "in ident1 " : "";
2513
2514 if (ci->type != CONF_ITEM_SECTION) {
2515 in_ident2 = NULL;
2516 } else {
2517 fr_rb_find((void **)&found, ci->ident2, child);
2518 in_ident2 = found == child? "in ident2 " : "";
2519 }
2520
2521 switch (child->type) {
2522 case CONF_ITEM_SECTION:
2523 {
2524 CONF_SECTION const *cs = cf_item_to_section(child);
2525
2526 DEBUG(" SECTION %p (%s %s) %s%s", child, cs->name1, cs->name2 ? cs->name2 : "<none>",
2527 in_ident1, in_ident2);
2528 }
2529 break;
2530
2531 case CONF_ITEM_PAIR:
2532 {
2533 CONF_PAIR const *cp = cf_item_to_pair(child);
2534 char const *lhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>");
2535 char const *rhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>");
2536
2537 DEBUG(" PAIR %p (%s%s%s %s %s%s%s) %s%s", child,
2538 lhs_quote, cp->attr, lhs_quote,
2539 fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"),
2540 rhs_quote, cp->value, rhs_quote,
2541 in_ident1, in_ident2);
2542 }
2543 break;
2544
2545 case CONF_ITEM_DATA:
2546 {
2547 CONF_DATA const *cd = cf_item_to_data(child);
2548
2549 DEBUG(" DATA %p (%s *)%s = %p %s%s", child,
2550 cd->type, cd->name ? cd->name : "", cd->data,
2551 in_ident1, in_ident2);
2552 break;
2553 }
2554
2555 default:
2556 DEBUG(" INVALID - %p", child);
2557 break;
2558 }
2559 }
2560}
2561
2562/** Ease of use from debugger
2563 */
2565{
2566 cf_item_debug(cp);
2567}
2568
2569/** Ease of use from debugger
2570 */
2572{
2573 cf_item_debug(cs);
2574}
2575
2576/*
2577 * Used when we don't need the children any more, as with
2578 *
2579 * if (0) { ... }
2580 */
2582{
2583 CONF_ITEM *child;
2584
2585 while ((child = cf_item_next(ci, NULL)) != NULL) {
2586 _cf_item_remove(ci, child);
2587 }
2588}
2589
2590void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
2591{
2592 char *spaces, *text;
2593
2594 fr_canonicalize_error(ci, &spaces, &text, slen, str);
2595
2596 cf_log_err(ci, "%s", msg);
2597 cf_log_err(ci, "%s", text);
2598 cf_log_perr(ci, "%s^", spaces);
2599
2601 talloc_free(text);
2602}
2603
2604static fr_sbuff_term_t const ref_char = FR_SBUFF_TERMS(L("."), L("["));
2606
2607/*
2608 * Create or find a CONF_PAIR, including parents.
2609 *
2610 * This is only used by the command-line argument '-S foo.bar=baz'
2611 */
2612int cf_pair_replace_or_add(CONF_SECTION *cs, char const *ref, char const *value)
2613{
2614 fr_sbuff_t in = FR_SBUFF_IN(ref, strlen(ref));
2615
2616 char name1_buff[256];
2617 char name2_buff[256];
2618
2619 fr_sbuff_t name1_sbuff = FR_SBUFF_OUT(name1_buff, sizeof(name1_buff));
2620 fr_sbuff_t name2_sbuff = FR_SBUFF_OUT(name2_buff, sizeof(name2_buff));
2621
2622 char const *name1 = name1_buff;
2623 char const *name2;
2624
2625 CONF_PAIR *cp;
2626 CONF_SECTION *subcs = cs;
2627
2628 /*
2629 * Walk the dotted path, creating any section that does not
2630 * exist. Each segment is copied out so the lookup sees the
2631 * segment alone, not the rest of the path. The last segment
2632 * is the pair name, and is stopped on by the trailing '\0'.
2633 */
2634 for (;;) {
2635 CONF_SECTION *found;
2636 size_t len;
2637
2638 if (fr_sbuff_out_bstrncpy_until(&len, &name1_sbuff, &in, SIZE_MAX, &ref_char, NULL) < 0) {
2639 fr_strerror_printf("Section name is too long in '%s'", ref);
2640 return -1;
2641 }
2642 if (len == 0) break;
2643
2644 switch (*fr_sbuff_current(&in)) {
2645 case '.':
2646 name2 = NULL;
2647 fr_sbuff_advance(&in, 1); /* Skip the '.' */
2648 break;
2649
2650 case '[':
2651 fr_sbuff_advance(&in, 1); /* Skip the '[' */
2652 if ((fr_sbuff_out_bstrncpy_until(&len, &name2_sbuff, &in, SIZE_MAX, &ref_char_end, NULL) < 0) ||
2653 (len == 0) || !fr_sbuff_is_char(&in, ']')) {
2654 fr_strerror_printf("Missing ']', or selector is empty or too long, in '%s'", ref);
2655 return -1;
2656 }
2657 name2 = name2_buff;
2658 fr_sbuff_advance(&in, 1); /* Skip the ']' */
2659 (void) fr_sbuff_next_if_char(&in, '.'); /* Skip the '.' in a[b].c */
2660 break;
2661
2662 /*
2663 * The final segment is the pair name. Replace the
2664 * pair if it exists, otherwise add it to the section
2665 * the walk arrived at.
2666 */
2667 case '\0':
2668 cp = cf_pair_find(subcs, name1);
2669 if (cp) return cf_pair_replace(subcs, cp, value);
2670
2671 cp = cf_pair_alloc(subcs, name1, value, T_OP_EQ, T_BARE_WORD, T_BARE_WORD);
2672 if (!cp) return -1;
2673 return 0;
2674
2675 /*
2676 * The copy only stops on a terminal or the end
2677 * of the input, so this cannot happen.
2678 */
2679 default:
2680 fr_assert_msg(0, "copy stopped on a non terminal character");
2681 return -1;
2682 }
2683
2684 /*
2685 * Find the named child section, creating it if it
2686 * does not exist. The parent is the section the walk
2687 * has reached so far, never the result of the lookup,
2688 * which is NULL on a miss.
2689 */
2690 found = cf_section_find(subcs, name1, name2);
2691 if (!found) found = cf_section_alloc(subcs, subcs, name1, name2);
2692 if (!found) return -1;
2693 subcs = found;
2694
2695 fr_sbuff_set_to_start(&name1_sbuff);
2696 fr_sbuff_set_to_start(&name2_sbuff);
2697 }
2698
2699 fr_strerror_printf("Empty section or pair name in '%s'", ref);
2700 return -1;
2701}
2702
static int const char char buffer[256]
Definition acutest.h:641
int const char * file
Definition acutest.h:855
va_end(args)
log_entry msg
Definition acutest.h:947
static int const char * fmt
Definition acutest.h:638
void int line
Definition acutest.h:810
va_start(args, fmt)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define RCSID(id)
Definition build.h:603
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:245
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition build.h:139
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:130
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
@ CMP_GT
a > b
Definition build.h:117
@ CMP_LT
a < b
Definition build.h:115
@ CMP_EQ
a == b
Definition build.h:116
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:300
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:1662
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:655
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:460
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:744
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:650
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:669
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
fr_rb_node_t ident2_node
Entry in the ident2 tree.
Definition cf_priv.h:56
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:107
CONF_ITEM * parent
Parent.
Definition cf_priv.h:61
fr_token_t name2_quote
The type of quoting around name2.
Definition cf_priv.h:112
#define CF_SECTION_MAX_DUP_ITEMS
Limit the number of indirect children that a section can have.
Definition cf_priv.h:165
void * base
Definition cf_priv.h:118
char const * name2
Second name token. Given foo bar {} would be bar.
Definition cf_priv.h:110
int argc
number of additional arguments
Definition cf_priv.h:114
char const * attr
Attribute name.
Definition cf_priv.h:80
char const * name
Additional qualification of type.
Definition cf_priv.h:199
#define cf_item_foreach_prev(_ci, _iter, _prev)
Iterate over the contents of a list in reverse order.
Definition cf_priv.h:230
@ CONF_ITEM_INVALID
Definition cf_priv.h:40
@ CONF_ITEM_PAIR
Definition cf_priv.h:41
@ CONF_ITEM_DATA
Definition cf_priv.h:43
@ CONF_ITEM_SECTION
Definition cf_priv.h:42
@ CONF_ITEM_COMMENT
A # ... line preserved verbatim from the input - only created when the parser is asked to keep commen...
Definition cf_priv.h:44
bool referenced
Was this item referenced in the config?
Definition cf_priv.h:69
fr_rb_tree_t * ident2
Tree to store the second identifier (name2 || name).
Definition cf_priv.h:64
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
int depth
Definition cf_priv.h:119
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:201
static bool cf_item_has_no_children(CONF_ITEM const *ci)
Check if the CONF_ITEM has no children.
Definition cf_priv.h:240
fr_dlist_head_t children
The head of the ordered list of children.
Definition cf_priv.h:59
fr_token_t * argv_quote
Definition cf_priv.h:116
fr_token_t op
Operator e.g. =, :=.
Definition cf_priv.h:83
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:78
bool pass2
do expansion in pass2.
Definition cf_priv.h:87
#define CF_SECTION_MAX_CHILDREN
Limit the number of direct children that a section can have.
Definition cf_priv.h:150
char const * filename
The file the config item was parsed from.
Definition cf_priv.h:71
fr_rb_tree_t * ident1
Tree to store the first identifier (name1 || type || attr).
Definition cf_priv.h:63
bool is_talloced
If true we can do extra checks.
Definition cf_priv.h:202
CONF_SECTION * template
Definition cf_priv.h:124
fr_rb_node_t ident1_node
Entry in the ident1 tree.
Definition cf_priv.h:55
char const * text
Comment text, with the leading # and any surrounding whitespace stripped.
Definition cf_priv.h:188
fr_dlist_t entry
Entry in dlist.
Definition cf_priv.h:58
#define cf_item_foreach_next(_ci, _iter, _prev)
Iterate over the contents of a list.
Definition cf_priv.h:220
enum conf_type CONF_ITEM_TYPE
char const ** argv
additional arguments
Definition cf_priv.h:115
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:186
char const * type
C type of data being stored.
Definition cf_priv.h:198
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:196
fr_token_t lhs_quote
Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition cf_priv.h:84
int lineno
The line number the config item began on.
Definition cf_priv.h:70
CONF_ITEM_TYPE type
Whether the config item is a config_pair, conf_section or cf_data.
Definition cf_priv.h:66
A # ... comment line preserved verbatim from the input.
Definition cf_priv.h:185
Internal data that is associated with a configuration section.
Definition cf_priv.h:195
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
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:619
static fr_cmp_ret_t _cf_ident2_cmp(void const *a, void const *b)
Compare the first and second identifiers of a child.
Definition cf_util.c:379
static void cf_item_init(CONF_ITEM *ci, CONF_ITEM_TYPE type, CONF_ITEM *parent, char const *filename, int lineno)
Initialize a CONF_ITEM, so we don't have repeated code.
Definition cf_util.c:527
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition cf_util.c:1787
void * _cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd)
Remove data from a configuration section.
Definition cf_util.c:2031
CONF_SECTION * _cf_section_find_parent(CONF_ITEM const *ci, char const *name1, char const *name2)
Find a parent CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1315
int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
Walk over a specific type of CONF_DATA.
Definition cf_util.c:2056
unsigned int cf_pair_count_descendents(CONF_SECTION const *cs)
Count the number of conf pairs beneath a section.
Definition cf_util.c:1706
void _cf_item_mark_parsed(CONF_ITEM *ci)
Mark an item as parsed.
Definition cf_util.c:1577
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:1654
static fr_sbuff_term_t const ref_char
Definition cf_util.c:2604
void cf_section_debug(CONF_SECTION *cs)
Ease of use from debugger.
Definition cf_util.c:2571
CONF_DATA * _cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
Find matching data in the specified section or one of its parents.
Definition cf_util.c:1903
static bool cf_preserve_comments
Definition cf_util.c:784
CONF_ITEM * cf_data_to_item(CONF_DATA const *cd)
Cast CONF_DATA to a CONF_ITEM.
Definition cf_util.c:741
CONF_ITEM * _cf_item_remove(CONF_ITEM *parent, CONF_ITEM *child)
Remove item from parent and fixup trees.
Definition cf_util.c:434
CONF_DATA const * _cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
Find user data in a config section.
Definition cf_util.c:1869
fr_token_t cf_section_argv_quote(CONF_SECTION const *cs, int argc)
Return the quoting for one of the variadic arguments.
Definition cf_util.c:1468
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:1721
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:2129
int cf_pair_replace_or_add(CONF_SECTION *cs, char const *ref, char const *value)
Definition cf_util.c:2612
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp, bool copy_meta)
Duplicate a CONF_PAIR.
Definition cf_util.c:1529
#define FILENAME_TRUNCATE
static CONF_DATA * cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
Allocate a new user data container.
Definition cf_util.c:1828
void cf_item_free_children(CONF_ITEM *ci)
Definition cf_util.c:2581
CONF_ITEM * cf_comment_to_item(CONF_COMMENT const *c)
Cast a CONF_COMMENT back to a CONF_ITEM.
Definition cf_util.c:767
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1405
void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt,...)
Log an error message relating to a CONF_ITEM.
Definition cf_util.c:2208
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1922
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:725
CONF_ITEM * _cf_parent(CONF_ITEM const *ci)
Return the parent of a CONF_ITEM.
Definition cf_util.c:563
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:1487
void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
Log an error message relating to a CONF_ITEM.
Definition cf_util.c:2231
static fr_sbuff_term_t const ref_char_end
Definition cf_util.c:2605
CONF_SECTION * cf_section_next(CONF_SECTION const *cs, CONF_SECTION const *curr)
Return the next child that's a CONF_SECTION.
Definition cf_util.c:1216
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1391
CONF_SECTION * _cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent, char const *name1, char const *name2, char const *filename, int lineno)
Allocate a CONF_SECTION.
Definition cf_util.c:870
CONF_ITEM * _cf_item_next(CONF_ITEM const *parent, CONF_ITEM const *curr)
Return the next child of the CONF_ITEM.
Definition cf_util.c:497
static void _pair_count(int *count, CONF_SECTION const *cs)
Callback to determine the number of pairs in a section.
Definition cf_util.c:1687
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:1247
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:671
CONF_ITEM * _cf_item_prev(CONF_ITEM const *ci, CONF_ITEM const *curr)
Return the next child of cs.
Definition cf_util.c:512
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:1640
CONF_DATA * cf_item_to_data(CONF_ITEM const *ci)
Cast CONF_ITEM to CONF_DATA performing a type check.
Definition cf_util.c:691
void _cf_filename_set(CONF_ITEM *ci, char const *filename)
Set the filename of a CONF_ITEM.
Definition cf_util.c:977
char const * cf_section_value_find(CONF_SECTION const *cs, char const *attr)
Find a pair in a CONF_SECTION.
Definition cf_util.c:1339
bool cf_item_is_comment(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_COMMENT.
Definition cf_util.c:750
CONF_SECTION * _cf_root(CONF_ITEM const *ci)
Return the top level CONF_SECTION holding all other CONF_ITEM.
Definition cf_util.c:545
CONF_COMMENT * cf_comment_alloc(CONF_SECTION *parent, char const *text)
Allocate a new comment item attached to parent.
Definition cf_util.c:821
void _cf_lineno_set(CONF_ITEM *ci, int lineno)
Set the line number of a CONF_ITEM.
Definition cf_util.c:989
void cf_preserve_comments_set(bool preserve)
Control whether the CF parser preserves # ... comments.
Definition cf_util.c:786
void _cf_log_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child, char const *file, int line, char const *fmt,...)
Log an error message in the context of a child pair of the specified parent.
Definition cf_util.c:2382
void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt,...)
Log an error message relating to a CONF_ITEM.
Definition cf_util.c:2320
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:1987
static int _cd_free(CONF_DATA *cd)
Free user data associated with CONF_DATA.
Definition cf_util.c:1812
void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
Log an error message relating to a CONF_ITEM.
Definition cf_util.c:2169
void _cf_log_perr_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt,...)
Log an error message in the context of a child pair of the specified parent.
Definition cf_util.c:2413
CONF_COMMENT * cf_item_to_comment(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_COMMENT (asserts on type mismatch).
Definition cf_util.c:758
static CONF_ITEM * cf_next(CONF_ITEM const *parent, CONF_ITEM const *current, CONF_ITEM_TYPE type)
Return the next child that's of the specified type.
Definition cf_util.c:48
bool _cf_expand_variables(void)
Definition cf_util.c:816
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition cf_util.c:1417
char const * _cf_filename(CONF_ITEM const *ci)
Return the filename the CONF_ITEM was parsed in.
Definition cf_util.c:591
bool _cf_preserve_comments(void)
Definition cf_util.c:796
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
Definition cf_util.c:633
bool _cf_item_is_parsed(CONF_ITEM *ci)
Return whether an item has already been parsed.
Definition cf_util.c:1589
void _cf_item_debug(CONF_ITEM const *ci)
Print out debugging information about a CONFIG_ITEM.
Definition cf_util.c:2437
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1772
static fr_cmp_ret_t cf_ident2_cmp(void const *a, void const *b)
Compare only the second identifier of a child.
Definition cf_util.c:329
#define IS_WILDCARD(_ident)
Definition cf_util.c:76
static CONF_ITEM * cf_prev(CONF_ITEM const *parent, CONF_ITEM const *current, CONF_ITEM_TYPE type)
Return the previous child that's of the specified type.
Definition cf_util.c:67
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1802
void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt,...)
Log a debug message relating to a CONF_ITEM.
Definition cf_util.c:2343
CONF_PAIR * cf_pair_first(CONF_SECTION const *cs)
Return the first child that's a CONF_PAIR.
Definition cf_util.c:1601
static CONF_ITEM * cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
Return the next child that's of the specified type with the specified identifiers.
Definition cf_util.c:89
static void truncate_filename(char const **e, char const **p, int *len, char const *filename)
Definition cf_util.c:2088
CONF_PAIR * cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *curr)
Return the next child that's a CONF_PAIR.
Definition cf_util.c:1614
void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
Definition cf_util.c:2590
CONF_SECTION * _cf_section_find_in_parent(CONF_ITEM const *ci, char const *name1, char const *name2)
Find an ancestor of the passed CONF_ITEM which has a child matching a specific name1 and optionally n...
Definition cf_util.c:1291
CONF_DATA const * _cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
Return the next item of user data.
Definition cf_util.c:1887
static CONF_ITEM * cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
Return the next child that's of the specified type with the specified identifiers.
Definition cf_util.c:186
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:605
static bool cf_expand_vars
Definition cf_util.c:809
char const * cf_comment_text(CONF_COMMENT const *c)
Definition cf_util.c:773
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
Definition cf_util.c:1052
CONF_PAIR * cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
Find a pair with a name matching attr in the specified section or one of its parents.
Definition cf_util.c:1668
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
Return variadic argument at the specified index.
Definition cf_util.c:1433
CONF_PAIR * cf_pair_prev(CONF_SECTION const *cs, CONF_PAIR const *curr)
Return the previous child that's a CONF_PAIR.
Definition cf_util.c:1627
static fr_cmp_ret_t _cf_ident1_cmp(void const *a, void const *b)
Compare the first identifier of a child.
Definition cf_util.c:272
void cf_expand_variables_set(bool expand)
Opt out of ${var} expansion when reading config (default: enabled).
Definition cf_util.c:811
fr_cmp_ret_t cf_section_name_cmp(CONF_SECTION const *cs, char const *name1, char const *name2)
Check if a given section matches the specified name1/name2 identifiers.
Definition cf_util.c:1358
int _cf_lineno(CONF_ITEM const *ci)
Return the lineno the CONF_ITEM was parsed at.
Definition cf_util.c:577
static int _cf_section_free(CONF_SECTION *cs)
Free a section and associated trees.
Definition cf_util.c:849
CONF_SECTION * cf_section_first(CONF_SECTION const *cs)
Return the first child in a CONF_SECTION.
Definition cf_util.c:1203
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:651
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:1268
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
Definition cf_util.c:1450
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1758
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair value in a given section with the given value.
Definition cf_util.c:1561
static unsigned int cf_section_item_count(CONF_SECTION const *cs, unsigned int *total)
Count the items in a section, giving up once the count reaches a limit.
Definition cf_util.c:1012
void cf_pair_debug(CONF_PAIR *cp)
Ease of use from debugger.
Definition cf_util.c:2564
int _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child)
Add a child.
Definition cf_util.c:394
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition cf_util.c:709
CONF_SECTION * cf_section_prev(CONF_SECTION const *cs, CONF_SECTION const *curr)
Return the previous child that's a CONF_SECTION.
Definition cf_util.c:1229
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1742
CONF_DATA const * _cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free, char const *filename, int lineno)
Add talloced user data to a config section.
Definition cf_util.c:1945
#define cf_item_add(_parent, _child)
Definition cf_util.h:85
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:295
#define cf_lineno_set(_ci, _lineno)
Definition cf_util.h:183
#define cf_parent(_cf)
Definition cf_util.h:115
#define cf_item_remove(_parent, _child)
Definition cf_util.h:88
#define cf_item_next(_parent, _curr)
Definition cf_util.h:91
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:198
#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:106
#define cf_filename_set(_ci, _filename)
Definition cf_util.h:180
#define cf_item_debug(_cf)
Definition cf_util.h:412
int(* cf_walker_t)(void *data, void *ctx)
Definition cf_util.h:78
#define CF_IDENT_ANY
Definition cf_util.h:80
static fr_atomic_queue_t ** aq
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:254
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
Test enumeration values.
Definition dict_test.h:92
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:242
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:620
static bool fr_dlist_entry_in_list(fr_dlist_t const *entry)
Check if a list entry is part of a list.
Definition dlist.h:145
static void * fr_dlist_prev(fr_dlist_head_t const *list_head, void const *ptr)
Get the previous item in a list.
Definition dlist.h:570
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
Definition dlist.h:921
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:360
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition dlist.h:537
talloc_free(hp)
#define LOG_DST
Definition network.c:29
#define DEBUG_ENABLED4
True if global debug level 1-4 messages are enabled.
Definition log.h:265
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition log.h:262
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition log.c:347
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
#define fr_log(_log, _lvl, _file, _line, _fmt,...)
Definition log.h:172
#define fr_vlog_perror(_log, _type, _file, _line, _rules, _fmt, _ap)
Definition log.h:180
char const * first_prefix
Prefix for the first line printed.
Definition log.h:122
char const * subsq_prefix
Prefix for subsequent lines.
Definition log.h:123
#define fr_vlog(_log, _lvl, _file, _line, _fmt, _ap)
Definition log.h:166
fr_log_type_t
Definition log.h:51
@ L_INFO
Informational message.
Definition log.h:52
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:121
long int ssize_t
fr_sbuff_err_t fr_sbuff_out_bstrncpy_until(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:860
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:883
#define fr_assert(_expr)
Definition rad_assert.h:37
static bool done
Definition radclient.c:80
static const char * spaces
Definition radict.c:185
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
Definition rb.c:807
int fr_rb_find(void **found, fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:586
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
Definition rb.c:850
void * fr_rb_remove_by_inline_node(fr_rb_tree_t *tree, fr_rb_node_t *node)
Remove an entry from the tree, using the node structure, without freeing the data.
Definition rb.c:748
int fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:637
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:876
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:269
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:319
The main red black tree structure.
Definition rb.h:71
static char const * name
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
Definition sbuff.c:2247
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:191
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define FR_SBUFF_OUT(_start, _len_or_end)
Set of terminal elements.
return count
Definition module.c:155
fr_aka_sim_id_type_t type
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:685
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
Definition talloc.c:665
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:757
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:289
#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 bool fr_assignment_op[T_TOKEN_LAST]
Definition token.c:234
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:33
fr_table_num_sorted_t const fr_token_quotes_table[]
Definition token.c:68
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:264
const bool fr_binary_op[T_TOKEN_LAST]
Definition token.c:282
@ T_INVALID
Definition token.h:37
@ T_BARE_WORD
Definition token.h:118
@ T_OP_EQ
Definition token.h:81
enum fr_token fr_token_t
#define FR_TABLE_NOT_FOUND
Macro to use as dflt.
Definition token.h:135
static fr_slen_t parent
Definition pair.h:864
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
int nonnull(2, 5))