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