The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 15c8b29095d264e55518ae7a19667e1d4de91923 $
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: 15c8b29095d264e55518ae7a19667e1d4de91923 $")
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
34static inline int8_t cf_ident2_cmp(void const *a, void const *b);
35static int8_t _cf_ident1_cmp(void const *a, void const *b);
36static int8_t _cf_ident2_cmp(void const *a, void const *b);
37
38/** Return the next child that's of the specified type
39 *
40 * @param[in] parent to return children from.
41 * @param[in] current child to start searching from.
42 * @param[in] type to search for.
43 * @return
44 * - The next #CONF_ITEM that's a child of ci matching type.
45 * - NULL if no #CONF_ITEM matches that criteria.
46 */
48{
50 if (ci->type == type) return ci;
51 }
52
53 return NULL;
54}
55
56/** Return the previos child that's of the specified type
57 *
58 * @param[in] parent to return children from.
59 * @param[in] current child to start searching from.
60 * @param[in] type to search for.
61 * @return
62 * - The next #CONF_ITEM that's a child of ci matching type.
63 * - NULL if no #CONF_ITEM matches that criteria.
64 */
65static inline CC_HINT(always_inline)
67{
69 if (ci->type == type) return ci;
70 }
71
72 return NULL;
73}
74
75#define IS_WILDCARD(_ident) (_ident == CF_IDENT_ANY)
76
77/** Return the next child that's of the specified type with the specified identifiers
78 *
79 * @param[in] parent The section we're searching in.
80 * @param[in] type of #CONF_ITEM we're searching for.
81 * @param[in] ident1 The first identifier.
82 * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
83 * can be used to match any ident2 value.
84 * @return
85 * - The first matching item.
86 * - NULL if no items matched.
87 */
88static CONF_ITEM *cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
89{
90 CONF_SECTION cs_find;
91 CONF_PAIR cp_find;
92 CONF_DATA cd_find;
93 CONF_ITEM *find;
94
95 if (!parent) return NULL;
96 if (cf_item_has_no_children(parent)) return NULL;
97
98 if (!ident1) return cf_next(parent, NULL, type);
99
100 switch (type) {
102 memset(&cs_find, 0, sizeof(cs_find));
103 cs_find.item.type = CONF_ITEM_SECTION;
104 cs_find.name1 = ident1;
105 if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
106
107 find = (CONF_ITEM *)&cs_find;
108 break;
109
110 case CONF_ITEM_PAIR:
111 fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
112
113 memset(&cp_find, 0, sizeof(cp_find));
114 cp_find.item.type = CONF_ITEM_PAIR;
115 cp_find.attr = ident1;
116
117 find = (CONF_ITEM *)&cp_find;
118 break;
119
120 case CONF_ITEM_DATA:
121 memset(&cd_find, 0, sizeof(cd_find));
122 cd_find.item.type = CONF_ITEM_DATA;
123 cd_find.type = ident1;
124 if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
125
126 find = (CONF_ITEM *)&cd_find;
127 break;
128
129 default:
130 fr_assert_fail(NULL);
131 return NULL;
132 }
133
134 /*
135 * No ident1, iterate over the child list
136 */
137 if (IS_WILDCARD(ident1)) {
139 if (find->type != ci->type) continue;
140
141 if (cf_ident2_cmp(find, ci) == 0) return ci;
142 }
143
144 return NULL;
145 }
146
147 /*
148 * No ident2, use the ident1 tree.
149 */
150 if (IS_WILDCARD(ident2)) return fr_rb_find(parent->ident1, find);
151
152 /*
153 * Only sections have an ident2 tree.
154 */
155 if (parent->type != CONF_ITEM_SECTION) return NULL;
156
157 /*
158 * Both ident1 and ident2 use the ident2 tree.
159 */
160 return fr_rb_find(parent->ident2, find);
161}
162
163/** Return the next child that's of the specified type with the specified identifiers
164 *
165 * @param[in] parent The section we're searching in.
166 * @param[in] prev item we found, or NULL to start from the beginning.
167 * @param[in] type of #CONF_ITEM we're searching for.
168 * @param[in] ident1 The first identifier.
169 * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
170 * can be used to match any ident2 value.
171 * @return
172 * - The first matching item.
173 * - NULL if no items matched.
174 */
175static CONF_ITEM *cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev,
176 CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
177{
178 CONF_SECTION cs_find;
179 CONF_PAIR cp_find;
180 CONF_DATA cd_find;
181 CONF_ITEM *find;
182
183 if (!parent) return NULL;
184
185 if (!prev) {
186 if (!ident1) return cf_next(parent, NULL, type);
187 return cf_find(parent, type, ident1, ident2);
188 }
189 if (!ident1) return cf_next(parent, prev, type);
190
191 switch (type) {
193 memset(&cs_find, 0, sizeof(cs_find));
194 cs_find.item.type = CONF_ITEM_SECTION;
195 cs_find.name1 = ident1;
196 if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
197
198 find = (CONF_ITEM *)&cs_find;
199 break;
200
201 case CONF_ITEM_PAIR:
202 fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
203
204 memset(&cp_find, 0, sizeof(cp_find));
205 cp_find.item.type = CONF_ITEM_PAIR;
206 cp_find.attr = ident1;
207
208 find = (CONF_ITEM *)&cp_find;
209 break;
210
211 case CONF_ITEM_DATA:
212 memset(&cd_find, 0, sizeof(cd_find));
213 cd_find.item.type = CONF_ITEM_DATA;
214 cd_find.type = ident1;
215 if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
216
217 find = (CONF_ITEM *)&cd_find;
218 break;
219
220 default:
221 fr_assert_fail(NULL);
222 return NULL;
223 }
224
225 if (IS_WILDCARD(ident1)) {
226 cf_item_foreach_next(parent, ci, prev) {
227 if (cf_ident2_cmp(ci, find) == 0) return ci;
228 }
229
230 return NULL;
231 }
232
233 if (IS_WILDCARD(ident2)) {
234 cf_item_foreach_next(parent, ci, prev) {
235 if (_cf_ident1_cmp(ci, find) == 0) return ci;
236
237 }
238
239 return NULL;
240 }
241
242 cf_item_foreach_next(parent, ci, prev) {
243 if (_cf_ident2_cmp(ci, find) == 0) return ci;
244 }
245
246 return NULL;
247}
248
249/** Compare the first identifier of a child
250 *
251 * For CONF_ITEM_PAIR this is 'attr'.
252 * For CONF_ITEM_SECTION this is 'name1'.
253 * For CONF_ITEM_DATA this is 'type'.
254 *
255 * @param[in] one First CONF_ITEM to compare.
256 * @param[in] two Second CONF_ITEM to compare.
257 * @return CMP(one, two)
258 */
259static inline int8_t _cf_ident1_cmp(void const *one, void const *two)
260{
261 int ret;
262
264
265 {
266 CONF_ITEM const *a = one;
267 CONF_ITEM const *b = two;
268
269 CMP_RETURN(a, b, type);
270 type = a->type;
271 }
272
273 switch (type) {
274 case CONF_ITEM_PAIR:
275 {
276 CONF_PAIR const *a = one;
277 CONF_PAIR const *b = two;
278
279 ret = strcmp(a->attr, b->attr);
280 return CMP(ret, 0);
281 }
282
284 {
285 CONF_SECTION const *a = one;
286 CONF_SECTION const *b = two;
287
288 ret = strcmp(a->name1, b->name1);
289 return CMP(ret, 0);
290 }
291
292 case CONF_ITEM_DATA:
293 {
294 CONF_DATA const *a = one;
295 CONF_DATA const *b = two;
296
297 ret = strcmp(a->type, b->type);
298 return CMP(ret, 0);
299 }
300
301 default:
302 fr_assert_fail(NULL);
303 return 0;
304 }
305}
306
307/** Compare only the second identifier of a child
308 *
309 * For CONF_ITEM_SECTION this is 'name2'.
310 * For CONF_ITEM_DATA this is 'name'.
311 *
312 * @param[in] one First CONF_ITEM to compare.
313 * @param[in] two Second CONF_ITEM to compare.
314 * @return CMP(one,two)
315 */
316static inline int8_t cf_ident2_cmp(void const *one, void const *two)
317{
318 CONF_ITEM const *ci = one;
319 int ret;
320
321 switch (ci->type) {
322 case CONF_ITEM_PAIR:
323 return 0;
324
326 {
327 CONF_SECTION const *a = one;
328 CONF_SECTION const *b = two;
329
330 if (!b->name2 && a->name2) return +1;
331 if (b->name2 && !a->name2) return -1;
332 if (!b->name2 && !a->name2) return 0;
333
334 ret = strcmp(a->name2, b->name2);
335 return CMP(ret, 0);
336 }
337
338 case CONF_ITEM_DATA:
339 {
340 CONF_DATA const *a = one;
341 CONF_DATA const *b = two;
342
343 if (!b->name && a->name) return +1;
344 if (b->name && !a->name) return -1;
345 if (!b->name && !a->name) return 0;
346
347 ret = strcmp(a->name, b->name);
348 return CMP(ret, 0);
349 }
350
351 default:
352 fr_assert_fail(NULL);
353 return 0;
354 }
355}
356
357/** Compare the first and second identifiers of a child
358 *
359 * For CONF_ITEM_SECTION this is 'name2'.
360 * For CONF_ITEM_DATA this is 'name'.
361 *
362 * @param[in] a First CONF_ITEM to compare.
363 * @param[in] b Second CONF_ITEM to compare.
364 * @return CMP(a, b)
365 */
366static int8_t _cf_ident2_cmp(void const *a, void const *b)
367{
368 int ret;
369
370 ret = _cf_ident1_cmp(a, b);
371 if (ret != 0) return ret;
372
373 return cf_ident2_cmp(a, b);
374}
375
376/** Add a child
377 *
378 * @param[in] parent to add child to.
379 * @param[in] child to add.
380 */
382{
383 fr_assert(parent != child);
384
385 if (!parent || !child) return;
386
387 /*
388 * New child, add child trees.
389 */
390 if (!parent->ident1) parent->ident1 = fr_rb_inline_alloc(parent, CONF_ITEM, ident1_node,
391 _cf_ident1_cmp, NULL);
392 fr_rb_insert(parent->ident1, child);
393 fr_dlist_insert_tail(&parent->children, child); /* Append to the list of children */
394
395 if (parent->type != CONF_ITEM_SECTION) return; /* Only sections can have ident2 trees */
396
397 if (!parent->ident2) parent->ident2 = fr_rb_inline_alloc(parent, CONF_ITEM, ident2_node,
398 _cf_ident2_cmp, NULL);
399 fr_rb_insert(parent->ident2, child); /* NULL ident2 is still a value */
400}
401
402/** Insert a child after a given one
403 *
404 * @param[in] parent to add child to.
405 * @param[in] prev previous
406 * @param[in] child to add.
407 */
409{
410 fr_assert(parent != child);
411 fr_assert(prev != child);
412
413 /*
414 * Must be given something. Can't insert at HEAD.
415 */
416 if (!parent || !child) return;
417
418 if (!prev) {
419 cf_item_add(parent, child);
420 return;
421 }
422
423 /*
424 * If there's a prev, then the ident trees must be there.
425 */
426 fr_assert(parent->ident1 != NULL);
427
428 fr_rb_insert(parent->ident1, child);
429 fr_dlist_insert_after(&parent->children, prev, child); /* insert in the list of children */
430
431 if (parent->type != CONF_ITEM_SECTION) return; /* only sections can have ident2 trees */
432
433 fr_assert(parent->ident2 != NULL);
434 fr_rb_insert(parent->ident2, child); /* NULL ident2 is still a value */
435}
436
437
438/** Remove item from parent and fixup trees
439 *
440 * @param[in] parent to remove child from.
441 * @param[in] child to remove.
442 * @return
443 * - The previous item (makes iteration easier)
444 * - NULL if the item wasn't set.
445 */
447{
448 CONF_ITEM *found = NULL;
449 CONF_ITEM *prev;
450 bool in_ident1, in_ident2;
451
452 if (!parent || cf_item_has_no_children(parent)) return NULL;
453 if (parent != child->parent) return NULL;
454
456 if (ci == child) {
457 found = ci;
458 break;
459 }
460 }
461
462 if (!found) return NULL;
463
464 /*
465 * Fixup the linked list
466 */
467 prev = fr_dlist_remove(&parent->children, child);
468
469 in_ident1 = (fr_rb_remove_by_inline_node(parent->ident1, &child->ident1_node) != NULL);
470
471 /*
472 * Only sections can have ident2 trees.
473 */
474 if (parent->type != CONF_ITEM_SECTION) {
475 in_ident2 = false;
476 } else {
477 in_ident2 = (fr_rb_remove_by_inline_node(parent->ident2, &child->ident2_node) != NULL);
478 }
479
480 /*
481 * Look for twins. They weren't in the tree initially,
482 * because "child" was there.
483 */
485 if (!in_ident1 && !in_ident2) break;
486
487 if (in_ident1 && (_cf_ident1_cmp(ci, child) == 0)) {
488 fr_rb_insert(parent->ident1, ci);
489 in_ident1 = false;
490 }
491
492 if (in_ident2 && (_cf_ident2_cmp(ci, child) == 0)) {
493 fr_rb_insert(parent->ident2, ci);
494 in_ident2 = false;
495 }
496 }
497
498 return prev;
499}
500
501/** Return the next child of the CONF_ITEM
502 *
503 * @param[in] parent to return children from.
504 * @param[in] curr child to start searching from.
505 * @return
506 * - The next #CONF_ITEM that's a child of cs.
507 * - NULL if no more #CONF_ITEM.
508 */
510{
511 if (!parent) return NULL;
512
513 return fr_dlist_next(&parent->children, curr);
514}
515
516/** Return the next child of cs
517 *
518 * @param[in] ci to return children from.
519 * @param[in] curr child to start searching from.
520 * @return
521 * - The next #CONF_ITEM that's a child of cs.
522 * - NULL if no more #CONF_ITEM.
523 */
525{
526 if (!ci) return NULL;
527
528 return fr_dlist_prev(&ci->children, curr);
529}
530
531/** Initialize a CONF_ITEM, so we don't have repeated code
532 *
533 * @param[in] ci the CONF_ITEM to initialize
534 * @param[in] type the type to set
535 * @param[in] parent the parent node hosting this one
536 * @param[in] filename which caused this node to be created
537 * @param[in] lineno where in the filename
538 */
539static void cf_item_init(CONF_ITEM *ci, CONF_ITEM_TYPE type, CONF_ITEM *parent, char const *filename, int lineno)
540{
541 ci->type = type;
542 ci->parent = parent;
543
544 fr_dlist_init(&ci->children, CONF_ITEM, entry);
545
546 if (filename) cf_filename_set(ci, filename);
547 if (lineno) cf_lineno_set(ci, lineno);
548}
549
550/** Return the top level #CONF_SECTION holding all other #CONF_ITEM
551 *
552 * @param[in] ci to traverse up from.
553 * @return
554 * - NULL if ci was NULL.
555 * - The top level #CONF_SECTION
556 */
558{
559 CONF_ITEM const *ci_p;
560
561 if (!ci) return NULL;
562
563 for (ci_p = ci; ci_p->parent; ci_p = ci_p->parent);
564
565 return cf_item_to_section(ci_p);
566}
567
568/** Return the parent of a #CONF_ITEM
569 *
570 * @param[in] ci to return the parent of.
571 * @return
572 * - NULL if ci was NULL or it has no parents.
573 * - The parent of ci.
574 */
576{
577 if (!ci) return NULL;
578
579 return ci->parent;
580}
581
582/** Return the lineno the #CONF_ITEM was parsed at
583 *
584 * @param[in] ci to return the location of.
585 * @return
586 * - -1 if the #CONF_ITEM was created programmatically.
587 * - >= 0 where in the config file the line was parsed from.
588 */
589int _cf_lineno(CONF_ITEM const *ci)
590{
591 if (!ci) return -1;
592
593 return ci->lineno;
594}
595
596/** Return the filename the #CONF_ITEM was parsed in
597 *
598 * @param[in] ci to return the location of.
599 * @return
600 * - NULL if the #CONF_ITEM was created programmatically.
601 * - The path of the config file the #CONF_ITEM was located in.
602 */
603char const *_cf_filename(CONF_ITEM const *ci)
604{
605 if (!ci) return NULL;
606
607 return ci->filename;
608}
609
610/** Determine if #CONF_ITEM is a #CONF_SECTION
611 *
612 * @param[in] ci to check.
613 * @return
614 * - true if ci is a #CONF_SECTION.
615 * - false if ci is another specialisation.
616 */
618{
619 if (!ci) return false;
620
621 return ci->type == CONF_ITEM_SECTION;
622}
623
624/** Determine if #CONF_ITEM is a #CONF_PAIR
625 *
626 * @param[in] ci to check.
627 * @return
628 * - true if ci is a #CONF_PAIR.
629 * - false if ci is another specialisation.
630 */
632{
633 if (!ci) return false;
634
635 return ci->type == CONF_ITEM_PAIR;
636}
637
638/** Determine if #CONF_ITEM is #CONF_DATA
639 *
640 * @param[in] ci to check.
641 * @return
642 * - true if ci is #CONF_DATA.
643 * - false if ci is another specialisation.
644 */
646{
647 if (!ci) return false;
648
649 return ci->type == CONF_ITEM_DATA;
650}
651
652/** Cast a #CONF_ITEM to a #CONF_PAIR
653 *
654 * @note Will assert if ci does not contain #CONF_PAIR.
655 *
656 * @param[in] ci to cast.
657 * @return
658 * - #CONF_PAIR.
659 * - NULL if ci was NULL.
660 *
661 * @hidecallergraph
662 */
664{
665 if (ci == NULL) return NULL;
666
668
669 return UNCONST(CONF_PAIR *, ci);
670}
671
672/** Cast a #CONF_ITEM to a #CONF_SECTION
673 *
674 * @note Will assert if ci does not contain #CONF_SECTION.
675 *
676 * @param[in] ci to cast.
677 * @return
678 * - #CONF_SECTION.
679 * - NULL if ci was NULL.
680 *
681 * @hidecallergraph
682 */
684{
685 if (ci == NULL) return NULL;
686
688
689 return UNCONST(CONF_SECTION *, ci);
690}
691
692/** Cast #CONF_ITEM to #CONF_DATA performing a type check
693 *
694 * @note Will assert if ci does not contain #CONF_DATA.
695 *
696 * @param[in] ci to cast.
697 * @return
698 * - #CONF_DATA.
699 * - NULL if ci was NULL.
700 *
701 * @hidecallergraph
702 */
704{
705 if (ci == NULL) return NULL;
706
708
709 return UNCONST(CONF_DATA *, ci);
710}
711
712/** Cast a #CONF_PAIR to a #CONF_ITEM
713 *
714 * @param[in] cp to cast.
715 * @return
716 * - The common #CONF_ITEM header.
717 * - NULL if cp was NULL.
718 *
719 * @hidecallergraph
720 */
722{
723 if (cp == NULL) return NULL;
724
725 return UNCONST(CONF_ITEM *, cp);
726}
727
728/** Cast a #CONF_SECTION to a #CONF_ITEM
729 *
730 * @param[in] cs to cast.
731 * @return
732 * - The common #CONF_ITEM header.
733 * - NULL if cs was NULL.
734 *
735 * @hidecallergraph
736 */
738{
739 if (cs == NULL) return NULL;
740
741 return UNCONST(CONF_ITEM *, cs);
742}
743
744/** Cast #CONF_DATA to a #CONF_ITEM
745 *
746 * @param[in] cd to cast.
747 * @return
748 * - The common #CONF_ITEM header.
749 * - NULL if cd was NULL.
750 *
751 * @hidecallergraph
752 */
754{
755 if (cd == NULL) return NULL;
756
757 return UNCONST(CONF_ITEM *, cd);
758}
759
760/** Free a section and associated trees
761 *
762 * @param[in] cs to free.
763 * @return 0
764 */
766{
767 if (cs->item.ident1) TALLOC_FREE(cs->item.ident1);
768 if (cs->item.ident2) TALLOC_FREE(cs->item.ident2);
769
770 return 0;
771}
772
773/** Allocate a #CONF_SECTION
774 *
775 * @param[in] ctx to allocate
776 * @param[in] parent #CONF_SECTION to hang this #CONF_SECTION off of.
777 * If parent is not NULL, the new section will be added as a child.
778 * @param[in] name1 Primary name.
779 * @param[in] name2 Secondary name.
780 * @param[in] filename Caller file name for debugging. May be overridden later.
781 * @param[in] lineno Caller line number for debugging. May be overridden later.
782 * @return
783 * - NULL on error.
784 * - A new #CONF_SECTION parented by parent.
785 */
787 char const *name1, char const *name2,
788 char const *filename, int lineno)
789{
790 CONF_SECTION *cs;
791 char buffer[1024];
792
793 if (!name1) return NULL;
794
795 if (name2 && parent) {
796 char const *p;
797
798 p = strchr(name2, '$');
799 if (p && (p[1] != '{')) p = NULL;
800
801 if (p) {
802 name2 = cf_expand_variables(parent->item.filename,
803 parent->item.lineno,
804 parent,
805 buffer, sizeof(buffer), name2, -1, NULL);
806
807 if (!name2) {
808 ERROR("Failed expanding section name");
809 return NULL;
810 }
811 }
812 }
813
814 cs = talloc_zero(ctx, CONF_SECTION);
815 if (!cs) return NULL;
816
818
819 MEM(cs->name1 = talloc_typed_strdup(cs, name1));
820 if (name2) {
821 MEM(cs->name2 = talloc_typed_strdup(cs, name2));
823 }
824 talloc_set_destructor(cs, _cf_section_free);
825
826 if (parent) {
827 CONF_DATA const *cd;
828 conf_parser_t *rule;
829
830 /*
831 * Look up the parents parsing rules for itself.
832 * If there are rules, then one of them might be
833 * parsing rules for this new child. If that
834 * happens, we push the child parsing rules to
835 * this new child.
836 */
838 if (cd) {
839 rule = cf_data_value(cd);
840
841 if ((rule->flags & CONF_FLAG_SUBSECTION) &&
842 rule->on_read && rule->subcs) {
843 conf_parser_t const *rule_p;
844
845 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
846 if ((rule_p->flags & CONF_FLAG_SUBSECTION) &&
847 rule->on_read &&
848 (strcmp(rule_p->name1, name1) == 0)) {
849 if (_cf_section_rule_push(cs, rule_p,
850 cd->item.filename, cd->item.lineno) < 0) {
851 error:
852 talloc_free(cs);
853 return NULL;
854 }
855
856 if (rule_p->on_read(ctx, NULL, NULL,
857 cf_section_to_item(cs), rule_p) < 0) goto error;
858 goto done;
859 }
860 }
861 }
862 }
863
864 /*
865 * Or, the parent may already have parse rules
866 * for this new child. In which case we push the
867 * child rules for this section, and then do the
868 * on_read callback.
869 */
871 if (cd) {
872 rule = cf_data_value(cd);
873 if ((rule->flags & CONF_FLAG_SUBSECTION) &&
874 rule->on_read) {
875 if (cf_section_rules_push(cs, rule->subcs) < 0) goto error;
876 if (rule->on_read(ctx, NULL, NULL, cf_section_to_item(cs), rule) < 0) goto error;
877 }
878 }
879
880 done:
881 cs->depth = parent->depth + 1;
882 cf_item_add(parent, &(cs->item));
883 }
884
885 return cs;
886}
887
888/** Set the filename of a #CONF_ITEM
889 *
890 * @param[in] ci to set filename on.
891 * @param[in] filename to set.
892 */
893void _cf_filename_set(CONF_ITEM *ci, char const *filename)
894{
896
897 ci->filename = talloc_typed_strdup(ci, filename);
898}
899
900/** Set the line number of a #CONF_ITEM
901 *
902 * @param[in] ci to set the lineno for.
903 * @param[in] lineno to set.
904 */
905void _cf_lineno_set(CONF_ITEM *ci, int lineno)
906{
907 ci->lineno = lineno;
908}
909
910/** Duplicate a configuration section
911 *
912 * @note recursively duplicates any child sections.
913 * @note does not duplicate any data associated with a section, or its child sections.
914 *
915 * @param[in] ctx to allocate memory in.
916 * @param[in] parent section (may be NULL).
917 * @param[in] cs to duplicate.
918 * @param[in] name1 of new section.
919 * @param[in] name2 of new section.
920 * @param[in] copy_meta Copy additional meta data for a section
921 * (like template, base, depth, parsed state,
922 * and variables).
923 * @return
924 * - A duplicate of the existing section.
925 * - NULL on error.
926 */
928 char const *name1, char const *name2, bool copy_meta)
929{
930 CONF_SECTION *new, *subcs;
931 CONF_PAIR *cp;
932
933 new = cf_section_alloc(ctx, parent, name1, name2);
934
935 if (copy_meta) {
936 new->template = cs->template;
937 new->base = cs->base;
938 new->depth = cs->depth;
939 }
940
941 cf_filename_set(new, cs->item.filename);
942 cf_lineno_set(new, cs->item.lineno);
943
944 cf_item_foreach(&cs->item, ci) {
945 switch (ci->type) {
947 subcs = cf_item_to_section(ci);
948 subcs = cf_section_dup(new, new, subcs,
949 cf_section_name1(subcs), cf_section_name2(subcs),
950 copy_meta);
951 if (!subcs) {
952 talloc_free(new);
953 return NULL;
954 }
955 break;
956
957 case CONF_ITEM_PAIR:
958 cp = cf_pair_dup(new, cf_item_to_pair(ci), copy_meta);
959 if (!cp) {
960 talloc_free(new);
961 return NULL;
962 }
963 break;
964
965 case CONF_ITEM_DATA: /* Skip data */
966 break;
967
969 fr_assert(0);
970 }
971 }
972
973 return new;
974}
975
976/** Return the first child in a CONF_SECTION
977 *
978 * @param[in] cs to return children from.
979 * @return
980 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
981 * - NULL if no #CONF_ITEM matches that criteria.
982 */
987
988/** Return the next child that's a #CONF_SECTION
989 *
990 * @param[in] cs to return children from.
991 * @param[in] curr child to start searching from.
992 * @return
993 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
994 * - NULL if no #CONF_ITEM matches that criteria.
995 */
1000
1001/** Return the previous child that's a #CONF_SECTION
1002 *
1003 * @param[in] cs to return children from.
1004 * @param[in] curr child to start searching from.
1005 * @return
1006 * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
1007 * - NULL if no #CONF_ITEM matches that criteria.
1008 */
1013
1014/** Find a CONF_SECTION with name1 and optionally name2.
1015 *
1016 * @param[in] cs The section we're searching in.
1017 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1018 * can be used to match any name1 value.
1019 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1020 * can be used to match any name2 value.
1021 * @return
1022 * - The first matching subsection.
1023 * - NULL if no subsections match.
1024 *
1025 * @hidecallergraph
1026 */
1028 char const *name1, char const *name2)
1029{
1031}
1032
1033/** Return the next matching section
1034 *
1035 * @param[in] cs The section we're searching in.
1036 * @param[in] prev section we found. May be NULL in which case
1037 * we just return the next section after prev.
1038 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1039 * can be used to match any name1 value.
1040 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1041 * can be used to match any name2 value.
1042 * @return
1043 * - The next CONF_SECTION.
1044 * - NULL if there are no more CONF_SECTIONs
1045 *
1046 * @hidecallergraph
1047 */
1049 char const *name1, char const *name2)
1050{
1052 CONF_ITEM_SECTION, name1, name2));
1053}
1054
1055/** Find an ancestor of the passed CONF_ITEM which has a child matching a specific name1 and optionally name2.
1056 *
1057 * @note Despite the name, this function also searches in ci for a matching item.
1058 *
1059 * Will walk up the configuration tree, searching in each parent until a matching section is found or
1060 * we hit the root.
1061 *
1062 * @param[in] ci The conf item we're searching back from.
1063 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1064 * can be used to match any name1 value.
1065 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1066 * can be used to match any name2 value.
1067 * @return
1068 * - The first matching subsection.
1069 * - NULL if no subsections match.
1070 */
1072 char const *name1, char const *name2)
1073{
1074 do {
1075 CONF_ITEM *found;
1076
1077 found = cf_find(ci, CONF_ITEM_SECTION, name1, name2);
1078 if (found) return cf_item_to_section(found);
1079 } while ((ci = cf_parent(ci)));
1080
1081 return NULL;
1082}
1083
1084/** Find a parent CONF_SECTION with name1 and optionally name2.
1085 *
1086 * @param[in] ci The section we're searching in.
1087 * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1088 * can be used to match any name1 value.
1089 * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1090 * can be used to match any name2 value.
1091 * @return
1092 * - The first matching subsection.
1093 * - NULL if no subsections match.
1094 */
1096 char const *name1, char const *name2)
1097{
1098 while ((ci = cf_parent(ci))) {
1099 CONF_SECTION *found;
1100
1101 if (!cf_item_is_section(ci)) continue; /* Could be data hanging off a pair*/
1102
1103 found = cf_item_to_section(ci);
1104
1105 if (cf_section_name_cmp(found, name1, name2) == 0) return found;
1106 }
1107
1108 return NULL;
1109}
1110
1111/** Find a pair in a #CONF_SECTION
1112 *
1113 * @param[in] cs the #CONF_SECTION to search in.
1114 * @param[in] attr to search for.
1115 * @return
1116 * - NULL if no pair can be found.
1117 * - The value of the pair found.
1118 */
1119char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr)
1120{
1121 CONF_PAIR *cp;
1122
1123 cp = cf_pair_find(cs, attr);
1124
1125 return (cp ? cp->value : NULL);
1126}
1127
1128/** Check if a given section matches the specified name1/name2 identifiers
1129 *
1130 * @param[in] cs to check.
1131 * @param[in] name1 identifier. May be CF_IDENT_ANY for wildcard matches.
1132 * @param[in] name2 identifier. May be CF_IDENT_ANY for wildcard matches.
1133 * @return
1134 * - >1 if cs is greater than the identifiers.
1135 * - 0 if cs matches the identifiers.
1136 * - <0 if cs is less than the identifiers.
1137 */
1138int8_t cf_section_name_cmp(CONF_SECTION const *cs, char const *name1, char const *name2)
1139{
1140 int8_t ret;
1141
1142 if (name1 != CF_IDENT_ANY) {
1143 ret = CMP(strcmp(cf_section_name1(cs), name1), 0);
1144 if (ret != 0) return ret;
1145 }
1146
1147 if (name2 != CF_IDENT_ANY) {
1148 char const *cs_name2 = cf_section_name2(cs);
1149
1150 if (!cs_name2) {
1151 if (!name2) return 0;
1152 return 1;
1153 }
1154
1155 return CMP(strcmp(cs_name2, name2), 0);
1156 }
1157
1158 return 0;
1159}
1160
1161/** Return the second identifier of a #CONF_SECTION
1162 *
1163 * @param[in] cs to return identifiers for.
1164 * @return
1165 * - The first identifier.
1166 * - NULL if cs was NULL or no name1 set.
1167 *
1168 * @hidecallergraph
1169 */
1170char const *cf_section_name1(CONF_SECTION const *cs)
1171{
1172 return (cs ? cs->name1 : NULL);
1173}
1174
1175/** Return the second identifier of a #CONF_SECTION
1176 *
1177 * @param[in] cs to return identifiers for.
1178 * @return
1179 * - The second identifier.
1180 * - NULL if cs was NULL or no name2 set.
1181 *
1182 * @hidecallergraph
1183 */
1184char const *cf_section_name2(CONF_SECTION const *cs)
1185{
1186 return (cs ? cs->name2 : NULL);
1187}
1188
1189/** Return name2 if set, else name1
1190 *
1191 * @param[in] cs to return identifiers for.
1192 * @return name1 or name2 identifier.
1193 *
1194 * @hidecallergraph
1195 */
1196char const *cf_section_name(CONF_SECTION const *cs)
1197{
1198 char const *name;
1199
1200 name = cf_section_name2(cs);
1201 if (name) return name;
1202
1203 return cf_section_name1(cs);
1204}
1205
1206/** Return variadic argument at the specified index
1207 *
1208 * @param[in] cs containing the arguments.
1209 * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1210 * @return the argument value or NULL.
1211 */
1212char const *cf_section_argv(CONF_SECTION const *cs, int argc)
1213{
1214 if (!cs || !cs->argv || (argc < 0) || (argc >= cs->argc)) return NULL;
1215
1216 return cs->argv[argc];
1217}
1218
1219/** Return the quoting of the name2 identifier
1220 *
1221 * @param[in] cs containing name2.
1222 * @return
1223 * - #T_BARE_WORD.
1224 * - #T_SINGLE_QUOTED_STRING.
1225 * - #T_BACK_QUOTED_STRING.
1226 * - #T_DOUBLE_QUOTED_STRING.
1227 * - #T_INVALID if cs was NULL.
1228 */
1230{
1231 if (!cs) return T_INVALID;
1232
1233 return cs->name2_quote;
1234}
1235
1236/** Return the quoting for one of the variadic arguments
1237 *
1238 * @param[in] cs containing the arguments.
1239 * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1240 * @return
1241 * - #T_BARE_WORD.
1242 * - #T_SINGLE_QUOTED_STRING.
1243 * - #T_BACK_QUOTED_STRING.
1244 * - #T_DOUBLE_QUOTED_STRING.
1245 * - #T_INVALID if cs was NULL or the index was invalid.
1246 */
1248{
1249 if (!cs || !cs->argv_quote || (argc < 0) || (argc > cs->argc)) return T_INVALID;
1250
1251 return cs->argv_quote[argc];
1252}
1253
1254/** Allocate a #CONF_PAIR
1255 *
1256 * @param[in] parent #CONF_SECTION to hang this #CONF_PAIR off of.
1257 * @param[in] attr name.
1258 * @param[in] value of #CONF_PAIR.
1259 * @param[in] op #T_OP_EQ, #T_OP_SET etc.
1260 * @param[in] lhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1261 * @param[in] rhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1262 * @return
1263 * - NULL on error.
1264 * - A new #CONF_SECTION parented by parent.
1265 */
1266CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value,
1267 fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
1268{
1269 CONF_PAIR *cp;
1270
1272 if (!attr) return NULL;
1273
1274 cp = talloc_zero(parent, CONF_PAIR);
1275 if (!cp) return NULL;
1276
1278
1279 cp->lhs_quote = lhs_quote;
1280 cp->rhs_quote = rhs_quote;
1281 cp->op = op;
1282
1283 cp->attr = talloc_typed_strdup(cp, attr);
1284 if (!cp->attr) {
1285 error:
1286 talloc_free(cp);
1287 return NULL;
1288 }
1289
1290 if (value) {
1291 cp->value = talloc_typed_strdup(cp, value);
1292 if (!cp->value) goto error;
1293 }
1294
1295 cf_item_add(parent, &(cp->item));
1296 return cp;
1297}
1298
1299/** Duplicate a #CONF_PAIR
1300 *
1301 * @param parent to allocate new pair in.
1302 * @param cp to duplicate.
1303 * @param copy_meta Copy additional meta data for a pair
1304 * @return
1305 * - NULL on error.
1306 * - A duplicate of the input pair.
1307 */
1309{
1310 CONF_PAIR *new;
1311
1313 fr_assert(cp);
1314
1315 new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), cp->op, cp->lhs_quote, cp->rhs_quote);
1316 if (!new) return NULL;
1317
1318 if (copy_meta) new->parsed = cp->parsed;
1319 cf_lineno_set(new, cp->item.lineno);
1320 cf_filename_set(new, cp->item.filename);
1321
1322 return new;
1323}
1324
1325/** Replace pair in a given section with a new pair, of the given value.
1326 *
1327 * @note A new pair with the same metadata as the #CONF_PAIR will be added
1328 * even if the #CONF_PAIR can't be found inside the #CONF_SECTION.
1329 *
1330 * @param[in] cs to replace pair in.
1331 * @param[in] cp to replace.
1332 * @param[in] value New value to assign to cp.
1333 * @return
1334 * - 0 on success.
1335 * - -1 on failure.
1336 */
1338{
1339 CONF_PAIR *new_cp;
1340
1341 if (!cs || !cp || !value) return -1;
1342
1343 /*
1344 * Remove the old CONF_PAIR
1345 */
1346 (void)cf_item_remove(cs, cp);
1347
1348 /*
1349 * Add the new CONF_PAIR
1350 */
1351 MEM(new_cp = cf_pair_dup(cs, cp, true));
1353 MEM(cp->value = talloc_typed_strdup(cp, value));
1354
1355 return 0;
1356}
1357
1358
1359/** Mark a pair as parsed
1360 *
1361 * @param[in] cp to mark as parsed.
1362 */
1364{
1365 cp->parsed = true;
1366}
1367
1368/** Return whether a pair has already been parsed
1369 *
1370 * @param[in] cp to check.
1371 * @return
1372 * - true if pair has been parsed.
1373 * - false if the pair hasn't been parsed.
1374 */
1376{
1377 return cp->parsed;
1378}
1379
1380/** Return the first child that's a #CONF_PAIR
1381 *
1382 * @param[in] cs to return children from.
1383 * @return
1384 * - The first #CONF_ITEM that's a child of cs and a CONF_PAIR.
1385 * - NULL if no #CONF_ITEM matches that criteria.
1386 */
1391
1392/** Return the next child that's a #CONF_PAIR
1393 *
1394 * @param[in] cs to return children from.
1395 * @param[in] curr child to start searching from.
1396 * @return
1397 * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1398 * - NULL if no #CONF_ITEM matches that criteria.
1399 */
1404
1405/** Return the previous child that's a #CONF_PAIR
1406 *
1407 * @param[in] cs to return children from.
1408 * @param[in] curr child to start searching from.
1409 * @return
1410 * - The previous #CONF_ITEM that's a child of cs and a CONF_PAIR.
1411 * - NULL if no #CONF_ITEM matches that criteria.
1412 */
1417
1418/** Search for a #CONF_PAIR with a specific name
1419 *
1420 * @param[in] cs to search in.
1421 * @param[in] attr to find.
1422 * @return
1423 * - The next matching #CONF_PAIR.
1424 * - NULL if none matched.
1425 */
1426CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *attr)
1427{
1428 return cf_item_to_pair(cf_find(cf_section_to_item(cs), CONF_ITEM_PAIR, attr, NULL));
1429}
1430
1431/** Find a pair with a name matching attr, after specified pair
1432 *
1433 * @param[in] cs to search in.
1434 * @param[in] prev Pair to search from (may be NULL).
1435 * @param[in] attr to find (may be NULL in which case any attribute matches).
1436 * @return
1437 * - The next matching #CONF_PAIR
1438 * - NULL if none matched.
1439 */
1440CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
1441{
1443}
1444
1445/** Find a pair with a name matching attr in the specified section or one of its parents
1446 *
1447 * @param[in] cs to search in. Will start in the current section
1448 * and work upwards.
1449 * @param[in] attr to find.
1450 * @return
1451 * - A matching #CONF_PAIR.
1452 * - NULL if none matched.
1453 */
1454CONF_PAIR *cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
1455{
1456 CONF_ITEM const *parent = cf_section_to_item(cs);
1457
1458 do {
1459 CONF_ITEM *found;
1460
1461 found = cf_find(parent, CONF_ITEM_PAIR, attr, NULL);
1462 if (found) return cf_item_to_pair(found);
1463 } while ((parent = cf_parent(parent)));
1464
1465 return NULL;
1466}
1467
1468/** Callback to determine the number of pairs in a section
1469 *
1470 * @param[out] count Where we store the number of pairs found.
1471 * @param[in] cs we're currently searching in.
1472 */
1473static void _pair_count(int *count, CONF_SECTION const *cs)
1474{
1475 CONF_ITEM const *ci = NULL;
1476
1477 while ((ci = cf_item_next(cs, ci))) {
1478 if (cf_item_is_section(ci)) {
1480 continue;
1481 }
1482
1483 (*count)++;
1484 }
1485}
1486
1487/** Count the number of conf pairs beneath a section
1488 *
1489 * @param[in] cs to search for items in.
1490 * @return The number of pairs nested within section.
1491 */
1493{
1494 int count = 0;
1495
1496 _pair_count(&count, cs);
1497
1498 return count;
1499}
1500
1501/** Count the number of times an attribute occurs in a parent section
1502 *
1503 * @param[in] cs to search for items in.
1504 * @param[in] attr to search for.
1505 * @return The number of pairs of that attribute type.
1506 */
1507unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
1508{
1509 size_t i;
1510 CONF_PAIR *cp = NULL;
1511
1512 for (i = 0; (cp = cf_pair_find_next(cs, cp, attr)); i++);
1513
1514 return i;
1515}
1516
1517/** Concatenate the values of any pairs with name attr
1518 *
1519 * @param[out] out where to write the concatenated values.
1520 * @param[in] cs to search in.
1521 * @param[in] attr to search for.
1522 * @param[in] sep to use to separate values
1523 * @return
1524 * - Length of the data written to out on success.
1525 * - < 0 on failure. Number of additional bytes required in buffer.
1526 */
1527fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep)
1528{
1529 fr_sbuff_t our_out = FR_SBUFF(out);
1530 CONF_PAIR *cp;
1531 fr_slen_t slen = 0;
1532 fr_sbuff_escape_rules_t e_rules = {
1533 .name = __FUNCTION__,
1534 .chr = '\\'
1535 };
1536
1537 if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
1538
1539 for (cp = cf_pair_find(cs, attr); cp;) {
1540 slen = fr_sbuff_in_escape(&our_out, cf_pair_value(cp),
1541 strlen(cf_pair_value(cp)), &e_rules);
1542 if (slen < 0) return slen;
1543
1544 cp = cf_pair_find_next(cs, cp, attr);
1545 if (cp && sep) {
1546 slen = fr_sbuff_in_strcpy(&our_out, sep);
1547 if (slen < 0) return slen;
1548 }
1549 }
1550
1551 FR_SBUFF_SET_RETURN(out, &our_out);
1552}
1553
1554/** Return the attr of a #CONF_PAIR
1555 *
1556 * Return the LHS value of a pair (the attribute).
1557 *
1558 * @param[in] pair to return the attribute for.
1559 * @return
1560 * - NULL if the pair was NULL.
1561 * - The attribute name of the pair.
1562 *
1563 * @hidecallergraph
1564 */
1565char const *cf_pair_attr(CONF_PAIR const *pair)
1566{
1567 return (pair ? pair->attr : NULL);
1568}
1569
1570/** Return the value of a #CONF_PAIR
1571 *
1572 * Return the RHS value of a pair (the value).
1573 *
1574 * @param[in] pair to return the value of.
1575 * @return
1576 * - NULL if pair was NULL or the pair has no value.
1577 * - The string value of the pair.
1578 *
1579 * @hidecallergraph
1580 */
1581char const *cf_pair_value(CONF_PAIR const *pair)
1582{
1583 return (pair ? pair->value : NULL);
1584}
1585
1586/** Return the operator of a pair
1587 *
1588 * @param[in] pair to return the operator of.
1589 * @return
1590 * - T_INVALID if pair was NULL.
1591 * - T_OP_* (one of the operator constants).
1592 *
1593 * @hidecallergraph
1594 */
1596{
1597 return (pair ? pair->op : T_INVALID);
1598}
1599
1600/** Return the value (lhs) quoting of a pair
1601 *
1602 * @param pair to extract value type from.
1603 * @return
1604 * - #T_BARE_WORD.
1605 * - #T_SINGLE_QUOTED_STRING.
1606 * - #T_BACK_QUOTED_STRING.
1607 * - #T_DOUBLE_QUOTED_STRING.
1608 * - #T_INVALID if the pair is NULL.
1609 */
1611{
1612 return (pair ? pair->lhs_quote : T_INVALID);
1613}
1614
1615/** Return the value (rhs) quoting of a pair
1616 *
1617 * @param pair to extract value type from.
1618 * @return
1619 * - #T_BARE_WORD.
1620 * - #T_SINGLE_QUOTED_STRING.
1621 * - #T_BACK_QUOTED_STRING.
1622 * - #T_DOUBLE_QUOTED_STRING.
1623 * - #T_INVALID if the pair is NULL.
1624 */
1626{
1627 return (pair ? pair->rhs_quote : T_INVALID);
1628}
1629
1630/** Free user data associated with #CONF_DATA
1631 *
1632 * @param[in] cd being freed.
1633 * @return 0
1634 */
1635static int _cd_free(CONF_DATA *cd)
1636{
1637 void *to_free;
1638
1639 memcpy(&to_free, &cd->data, sizeof(to_free));
1640
1641 if (cd->free) talloc_decrease_ref_count(to_free); /* Also works OK for non-reference counted chunks */
1642
1643 return 0;
1644}
1645
1646/** Allocate a new user data container
1647 *
1648 * @param[in] parent #CONF_PAIR, or #CONF_SECTION to hang CONF_DATA off of.
1649 * @param[in] data being added.
1650 * @param[in] type of data being added.
1651 * @param[in] name String identifier of the user data.
1652 * @param[in] do_free function, called when the parent #CONF_SECTION is being freed.
1653 * @return
1654 * - CONF_DATA on success.
1655 * - NULL on error.
1656 */
1657static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
1658{
1659 CONF_DATA *cd;
1660
1661 cd = talloc_zero(parent, CONF_DATA);
1662 if (!cd) return NULL;
1663
1665
1666 /*
1667 * strdup so if the data is freed, we can
1668 * still remove it from the section without
1669 * explosions.
1670 */
1671 if (data) {
1672 cd->type = talloc_typed_strdup(cd, type);
1673 cd->data = data;
1674 }
1675 if (name) cd->name = talloc_typed_strdup(cd, name);
1676
1677 if (do_free) {
1678 cd->free = true;
1679 talloc_set_destructor(cd, _cd_free);
1680 }
1681
1682 cf_item_add(parent, cd);
1683 return cd;
1684}
1685
1686/** Find user data in a config section
1687 *
1688 * @param[in] ci The section to search for data in.
1689 * @param[in] type of user data. Used for name spacing and walking over a specific
1690 * type of user data.
1691 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1692 * may be used to match on type only.
1693 * @return
1694 * - The user data.
1695 * - NULL if no user data exists.
1696 */
1697CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
1698{
1700}
1701
1702/** Return the next item of user data
1703 *
1704 * @param[in] ci The section to search for data in.
1705 * @param[in] prev section we found. May be NULL in which case
1706 * we just return the next section after prev.
1707 * @param[in] type of user data. Used for name spacing and walking over a specific
1708 * type of user data.
1709 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1710 * can be used to match any name2 value.
1711 * @return
1712 * - The next matching #CONF_DATA.
1713 * - NULL if there is no more matching #CONF_DATA.
1714 */
1715CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
1716{
1718}
1719
1720/** Find matching data in the specified section or one of its parents
1721 *
1722 * @param[in] ci The section to search for data in.
1723 * @param[in] type of user data. Used for name spacing and walking over a specific
1724 * type of user data.
1725 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1726 * may be used to match on type only.
1727 * @return
1728 * - The next matching #CONF_DATA.
1729 * - NULL if there is no more matching #CONF_DATA.
1730 */
1731CONF_DATA *_cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
1732{
1733 CONF_ITEM const *parent = ci;
1734
1735 do {
1736 CONF_ITEM *found;
1737
1739 if (found) return cf_item_to_data(found);
1740 } while ((parent = cf_parent(parent)));
1741
1742 return NULL;
1743}
1744
1745/** Return the user assigned value of #CONF_DATA
1746 *
1747 * @param[in] cd to return value of.
1748 * @return the user data stored within the #CONF_DATA.
1749 */
1750void *cf_data_value(CONF_DATA const *cd)
1751{
1752 void *to_return;
1753
1754 if (!cd) return NULL;
1755
1756 memcpy(&to_return, &cd->data, sizeof(to_return));
1757
1758 return to_return;
1759}
1760
1761/** Add talloced user data to a config section
1762 *
1763 * @param[in] ci to add data to.
1764 * @param[in] data to add.
1765 * @param[in] name String identifier of the user data.
1766 * @param[in] do_free Function to free user data when the CONF_SECTION is freed.
1767 * @param[in] filename Source file the #CONF_DATA was added in.
1768 * @param[in] lineno the #CONF_DATA was added at.
1769 * @return
1770 * - #CONF_DATA - opaque handle to the stored data - on success.
1771 * - NULL error.
1772 */
1773CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free,
1774 char const *filename, int lineno)
1775{
1776 CONF_DATA *cd;
1777 CONF_DATA const *found;
1778 char const *type = NULL;
1779
1780 if (!ci) return NULL;
1781
1782 if (data) type = talloc_get_name(data);
1783
1784 /*
1785 * Already exists. Can't add it.
1786 */
1787 found = _cf_data_find(ci, type, name);
1788 if (found) {
1789 return NULL;
1790 }
1791
1792 cd = cf_data_alloc(ci, data, type, name, do_free);
1793 if (!cd) {
1794 cf_log_err(ci, "Failed allocating data");
1795 return NULL;
1796 }
1797 cd->is_talloced = true;
1798 cf_filename_set(cd, filename);
1799 cf_lineno_set(cd, lineno);
1800
1801 return cd;
1802}
1803
1804/** Add non-talloced user data to a config section
1805 *
1806 * @param[in] ci to add data to.
1807 * @param[in] data to add.
1808 * @param[in] type identifier of the user data.
1809 * @param[in] name String identifier of the user data.
1810 * @param[in] filename Source file the #CONF_DATA was added in.
1811 * @param[in] lineno the #CONF_DATA was added at.
1812 * - #CONF_DATA - opaque handle to the stored data - on success.
1813 * - NULL error.
1814 */
1815CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name,
1816 char const *filename, int lineno)
1817{
1818 CONF_DATA *cd;
1819 CONF_DATA const *found;
1820
1821 /*
1822 * Already exists. Can't add it.
1823 */
1824 found = _cf_data_find(ci, type, name);
1825 if (found) {
1826 /*
1827 * Suppress these, as it's OK for the conf_parser_t in main_config.c
1828 */
1829 if (strcmp(type, "conf_parser_t") == 0) return NULL;
1830
1831 cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type,
1832 name, found->item.filename, found->item.lineno);
1833 return NULL;
1834 }
1835
1836 cd = cf_data_alloc(ci, data, type, name, false);
1837 if (!cd) {
1838 cf_log_err(ci, "Failed allocating data");
1839 return NULL;
1840 }
1841 cd->is_talloced = false;
1842 cf_filename_set(cd, filename);
1843 cf_lineno_set(cd, lineno);
1844
1845 return cd;
1846}
1847
1848/** Remove data from a configuration section
1849 *
1850 * @note If cd was not found it will not be freed, and it is the caller's responsibility
1851 * to free it explicitly, or free the section it belongs to.
1852 *
1853 * @param[in] parent to remove data from.
1854 * @param[in] cd opaque handle of the stored data.
1855 * @return
1856 * - The value stored within the data (if cd is valid and was found and removed).
1857 * - NULL if not found.
1858 */
1860{
1861 void *data;
1862
1863 if (!cd) return NULL;
1864
1865 (void)cf_item_remove(parent, cd);
1866
1867 talloc_set_destructor(cd, NULL); /* Disarm the destructor */
1868 memcpy(&data, &cd->data, sizeof(data));
1870
1871 return data;
1872}
1873
1874/** Walk over a specific type of CONF_DATA
1875 *
1876 * @param[in] ci containing the CONF_DATA to walk over.
1877 * @param[in] type of CONF_DATA to walk over.
1878 * @param[in] cb to call when we find CONF_DATA of the specified type.
1879 * @param[in] ctx to pass to cb.
1880 * @return
1881 * - 0 on success.
1882 * - -1 on failure.
1883 */
1884int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
1885{
1886 CONF_DATA *cd;
1888 int ret = 0;
1889
1890 if (!ci->ident2) return 0;
1891
1892 for (ci = fr_rb_iter_init_inorder(&iter, ci->ident2);
1893 ci;
1894 ci = fr_rb_iter_next_inorder(&iter)) {
1895 /*
1896 * We're walking ident2, not all of the items will be data
1897 */
1898 if (ci->type != CONF_ITEM_DATA) continue;
1899
1900 cd = (void *) ci;
1901 if ((cd->type != type) && (strcmp(cd->type, type) != 0)) continue;
1902
1903 ret = cb(UNCONST(void *, cd->data), ctx);
1904 if (ret) {
1905 break;
1906 }
1907 }
1908
1909 return ret;
1910}
1911
1912static inline CC_HINT(nonnull) void truncate_filename(char const **e, char const **p, int *len, char const *filename)
1913{
1914 size_t flen;
1915 char const *q;
1916
1917 #define FILENAME_TRUNCATE 60
1918
1919 *p = filename;
1920 *e = "";
1921
1922 flen = talloc_array_length(filename) - 1;
1923 if (flen <= FILENAME_TRUNCATE) {
1924 *len = (int)flen;
1925 return;
1926 }
1927
1928 *p += flen - FILENAME_TRUNCATE;
1929 *len = FILENAME_TRUNCATE;
1930
1931 q = strchr(*p, FR_DIR_SEP);
1932 if (q) {
1933 q++;
1934 *p += (q - *p);
1935 *len -= (q - *p);
1936 }
1937
1938 *e = "...";
1939}
1940
1941/** Check to see if the CONF_PAIR value is present in the specified table
1942 *
1943 * If it's not present, return an error and produce a helpful log message
1944 *
1945 * @param[out] out The result of parsing the pair value.
1946 * @param[in] table to look for string values in.
1947 * @param[in] table_len Length of the table.
1948 * @param[in] cp to parse.
1949 * @return
1950 * - 0 on success.
1951 * - -1 on failure.
1952 */
1953int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
1954{
1955 char *list = NULL;
1956 int32_t res;
1957 size_t i;
1958
1960 if (res != FR_TABLE_NOT_FOUND) {
1961 *out = res;
1962 return 0;
1963 }
1964
1965 for (i = 0; i < table_len; i++) MEM(list = talloc_asprintf_append_buffer(list, "'%s', ", table[i].name.str));
1966
1967 if (!list) {
1968 cf_log_err(cp, "Internal error parsing %s: Table was empty", cf_pair_attr(cp));
1969 return -1;
1970 }
1971
1972 /*
1973 * Trim the final ", "
1974 */
1975 MEM(list = talloc_bstr_realloc(NULL, list, talloc_array_length(list) - 3));
1976
1977 cf_log_err(cp, "Invalid value \"%s\". Expected one of %s", cf_pair_value(cp), list);
1978
1979 talloc_free(list);
1980
1981 return -1;
1982}
1983
1984/** Log an error message relating to a #CONF_ITEM
1985 *
1986 * @param[in] type of log message.
1987 * @param[in] ci #CONF_ITEM to print file/lineno for.
1988 * @param[in] file src file the log message was generated in.
1989 * @param[in] line number the log message was generated on.
1990 * @param[in] fmt of the message.
1991 * @param[in] ap Message args.
1992 */
1993void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
1994{
1995 va_list aq;
1996
1997 if ((type == L_DBG) && !DEBUG_ENABLED) return;
1998
1999 if (!ci || !ci->filename || !*ci->filename || (*ci->filename == '<') ||
2000 (((type == L_DBG) || (type == L_INFO)) && !DEBUG_ENABLED4)) {
2001 va_copy(aq, ap);
2003 va_end(aq);
2004 return;
2005 }
2006
2007 {
2008 char const *e, *p;
2009 int len;
2010 char *msg;
2011
2012 truncate_filename(&e, &p, &len, ci->filename);
2013
2014 va_copy(aq, ap);
2015 msg = fr_vasprintf(NULL, fmt, aq);
2016 va_end(aq);
2017
2018 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2020 }
2021}
2022
2023/** Log an error message relating to a #CONF_ITEM
2024 *
2025 * @param[in] type of log message.
2026 * @param[in] file src file the log message was generated in.
2027 * @param[in] line number the log message was generated on.
2028 * @param[in] ci #CONF_ITEM to print file/lineno for.
2029 * @param[in] fmt of the message.
2030 * @param[in] ... Message args.
2031 */
2032void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2033{
2034 va_list ap;
2035
2036 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2037
2038 va_start(ap, fmt);
2039 _cf_vlog(type, ci, file, line, fmt, ap);
2040 va_end(ap);
2041}
2042
2043/** Log an error message relating to a #CONF_ITEM
2044 *
2045 * Drains the fr_strerror() stack emitting one or more error messages.
2046 *
2047 * @param[in] type of log message.
2048 * @param[in] file src file the log message was generated in.
2049 * @param[in] line number the log message was generated on.
2050 * @param[in] ci #CONF_ITEM to print file/lineno for.
2051 * @param[in] f_rules Additional optional formatting controls.
2052 * @param[in] fmt of the message.
2053 * @param[in] ap Message args.
2054 */
2055void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2056 fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
2057{
2058 va_list aq;
2059
2060 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2061
2062 if (!ci || !ci->filename) {
2063 va_copy(aq, ap);
2064 fr_vlog_perror(LOG_DST, type, file, line, f_rules, fmt, aq);
2065 va_end(aq);
2066 return;
2067 }
2068
2069 {
2070 char const *e, *p;
2071 int len;
2072 char *prefix;
2073 TALLOC_CTX *thread_log_pool;
2074 TALLOC_CTX *pool;
2075 fr_log_perror_format_t our_f_rules;
2076
2077 if (f_rules) {
2078 our_f_rules = *f_rules;
2079 } else {
2080 our_f_rules = (fr_log_perror_format_t){};
2081 }
2082
2083 /*
2084 * Get some scratch space from the logging code
2085 */
2086 thread_log_pool = fr_log_pool_init();
2087 pool = talloc_new(thread_log_pool);
2088
2089 truncate_filename(&e, &p, &len, ci->filename);
2090
2091 /*
2092 * Create the file location string
2093 */
2094 prefix = fr_asprintf(pool, "%s%.*s[%d]: ", e, len, p, ci->lineno);
2095
2096 /*
2097 * Prepend it to an existing first prefix
2098 */
2099 if (f_rules && f_rules->first_prefix) {
2100 char *first;
2101
2102 first = talloc_bstrdup(pool, prefix);
2103 talloc_buffer_append_buffer(pool, first, f_rules->first_prefix);
2104
2105 our_f_rules.first_prefix = first;
2106 } else {
2107 our_f_rules.first_prefix = prefix;
2108 }
2109
2110 /*
2111 * Prepend it to an existing subsq prefix
2112 */
2113 if (f_rules && f_rules->subsq_prefix) {
2114 char *subsq;
2115
2116 subsq = talloc_bstrdup(pool, prefix);
2117 talloc_buffer_append_buffer(pool, subsq, f_rules->subsq_prefix);
2118
2119 our_f_rules.subsq_prefix = subsq;
2120 } else {
2121 our_f_rules.subsq_prefix = prefix;
2122 }
2123
2124 va_copy(aq, ap);
2125 fr_vlog_perror(LOG_DST, type, file, line, &our_f_rules, fmt, aq);
2126 va_end(aq);
2127
2128 talloc_free(pool);
2129 }
2130}
2131
2132/** Log an error message relating to a #CONF_ITEM
2133 *
2134 * Drains the fr_strerror() stack emitting one or more error messages.
2135 *
2136 * @param[in] type of log message.
2137 * @param[in] file src file the log message was generated in.
2138 * @param[in] line number the log message was generated on.
2139 * @param[in] ci #CONF_ITEM to print file/lineno for.
2140 * @param[in] f_rules Additional optional formatting controls.
2141 * @param[in] fmt of the message.
2142 * @param[in] ... Message args.
2143 */
2144void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2145 fr_log_perror_format_t const *f_rules, char const *fmt, ...)
2146{
2147 va_list ap;
2148
2149 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2150
2151 va_start(ap, fmt);
2152 _cf_vlog_perr(type, ci, file, line, f_rules, fmt, ap);
2153 va_end(ap);
2154}
2155
2156/** Log a debug message relating to a #CONF_ITEM
2157 *
2158 * Always emits a filename/lineno prefix if available
2159 *
2160 * @param[in] type of log message.
2161 * @param[in] file src file the log message was generated in.
2162 * @param[in] line number the log message was generated on.
2163 * @param[in] ci #CONF_ITEM to print file/lineno for.
2164 * @param[in] fmt of the message.
2165 * @param[in] ... Message args.
2166 */
2167void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2168{
2169 va_list ap;
2170
2171 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2172
2173 if (!ci || !ci->filename) {
2174 va_start(ap, fmt);
2175 fr_vlog(LOG_DST, type, file, line, fmt, ap);
2176 va_end(ap);
2177 return;
2178 }
2179
2180 {
2181 char const *e, *p;
2182 int len;
2183 char *msg;
2184
2185 truncate_filename(&e, &p, &len, ci->filename);
2186
2187 va_start(ap, fmt);
2188 msg = fr_vasprintf(NULL, fmt, ap);
2189 va_end(ap);
2190
2191 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2193 }
2194}
2195
2196/** Log an error message in the context of a child pair of the specified parent
2197 *
2198 * @param[in] parent containing the pair.
2199 * @param[in] child name to use as a logging context.
2200 * @param[in] type of log message.
2201 * @param[in] file src file the log message was generated in.
2202 * @param[in] line number the log message was generated on.
2203 * @param[in] fmt of the message.
2204 * @param[in] ... Message args.
2205 */
2207 char const *file, int line, char const *fmt, ...)
2208{
2209 va_list ap;
2210 CONF_PAIR const *cp;
2211
2212 cp = cf_pair_find(parent, child);
2213 if (cp) {
2214 va_start(ap, fmt);
2215 _cf_vlog(type, CF_TO_ITEM(cp), file, line, fmt, ap);
2216 va_end(ap);
2217 return;
2218 }
2219
2220 va_start(ap, fmt);
2222 va_end(ap);
2223}
2224
2225
2226/** Log an error message in the context of a child pair of the specified parent
2227 *
2228 * @param[in] parent containing the pair.
2229 * @param[in] child name to use as a logging context.
2230 * @param[in] type of log message.
2231 * @param[in] file src file the log message was generated in.
2232 * @param[in] line number the log message was generated on.
2233 * @param[in] f_rules Line prefixes.
2234 * @param[in] fmt of the message.
2235 * @param[in] ... Message args.
2236 */
2238 char const *file, int line, fr_log_perror_format_t const *f_rules,
2239 char const *fmt, ...)
2240{
2241 va_list ap;
2242 CONF_PAIR const *cp;
2243
2244 cp = cf_pair_find(parent, child);
2245 if (cp) {
2246 va_start(ap, fmt);
2247 _cf_vlog_perr(type, CF_TO_ITEM(cp), file, line, f_rules, fmt, ap);
2248 va_end(ap);
2249 return;
2250 }
2251
2252 va_start(ap, fmt);
2253 _cf_vlog_perr(type, CF_TO_ITEM(parent), file, line, f_rules, fmt, ap);
2254 va_end(ap);
2255}
2256
2257/** Print out debugging information about a CONFIG_ITEM
2258 *
2259 * @param[in] ci being debugged.
2260 */
2262{
2263 /*
2264 * Print summary of the item
2265 */
2266 switch (ci->type) {
2267 case CONF_ITEM_SECTION:
2268 {
2269 CONF_SECTION const *cs = cf_item_to_section(ci);
2270 int i;
2271
2272 DEBUG("SECTION - %p", cs);
2273 DEBUG(" name1 : %s", cs->name1);
2274 DEBUG(" name2 : %s", cs->name2 ? cs->name2 : "<none>");
2275 DEBUG(" name2_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cs->name2_quote, "<INVALID>"));
2276 DEBUG(" argc : %d", cs->argc);
2277
2278 for (i = 0; i < cs->argc; i++) {
2279 char const *quote = fr_table_str_by_value(fr_token_quotes_table, cs->argv_quote[i], "<INVALID>");
2280 DEBUG(" argv[%i] : %s%s%s", i, quote, cs->argv[i], quote);
2281 }
2282 }
2283 break;
2284
2285 case CONF_ITEM_PAIR:
2286 {
2287 CONF_PAIR const *cp = cf_item_to_pair(ci);
2288
2289 DEBUG("PAIR - %p", cp);
2290 DEBUG(" attr : %s", cp->attr);
2291 DEBUG(" value : %s", cp->value);
2292 DEBUG(" operator : %s", fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"));
2293 DEBUG(" lhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>"));
2294 DEBUG(" rhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>"));
2295 DEBUG(" pass2 : %s", cp->pass2 ? "yes" : "no");
2296 DEBUG(" parsed : %s", cp->parsed ? "yes" : "no");
2297 }
2298 break;
2299
2300 case CONF_ITEM_DATA:
2301 {
2302 CONF_DATA const *cd = cf_item_to_data(ci);
2303
2304 DEBUG("DATA - %p", cd);
2305 DEBUG(" type : %s", cd->type);
2306 DEBUG(" name : %s", cd->name);
2307 DEBUG(" data : %p", cd->data);
2308 DEBUG(" free wth prnt : %s", cd->free ? "yes" : "no");
2309 }
2310 break;
2311
2312 default:
2313 DEBUG("INVALID - %p", ci);
2314 return;
2315 }
2316
2317 DEBUG(" filename : %s", ci->filename);
2318 DEBUG(" line : %i", ci->lineno);
2319 if (ci->parent) DEBUG(" next : %p", fr_dlist_next(&ci->parent->children, ci));
2320 DEBUG(" parent : %p", ci->parent);
2321 DEBUG(" children : %s", cf_item_has_no_children(ci) ? "no" : "yes");
2322 DEBUG(" ident1 tree : %p (%u entries)", ci->ident1, ci->ident1 ? fr_rb_num_elements(ci->ident1) : 0);
2323 DEBUG(" ident2 tree : %p (%u entries)", ci->ident2, ci->ident2 ? fr_rb_num_elements(ci->ident2) : 0);
2324
2325 if (cf_item_has_no_children(ci)) return;
2326
2327 /*
2328 * Print summary of the item's children
2329 */
2330 DEBUG("CHILDREN");
2331
2332 cf_item_foreach(ci, child) {
2333 char const *in_ident1, *in_ident2;
2334
2335 in_ident1 = fr_rb_find(ci->ident1, child) == child? "in ident1 " : "";
2336
2337 if (ci->type != CONF_ITEM_SECTION) {
2338 in_ident2 = false;
2339 } else {
2340 in_ident2 = fr_rb_find(ci->ident2, child) == child? "in ident2 " : "";
2341 }
2342
2343 switch (child->type) {
2344 case CONF_ITEM_SECTION:
2345 {
2346 CONF_SECTION const *cs = cf_item_to_section(child);
2347
2348 DEBUG(" SECTION %p (%s %s) %s%s", child, cs->name1, cs->name2 ? cs->name2 : "<none>",
2349 in_ident1, in_ident2);
2350 }
2351 break;
2352
2353 case CONF_ITEM_PAIR:
2354 {
2355 CONF_PAIR const *cp = cf_item_to_pair(child);
2356 char const *lhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>");
2357 char const *rhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>");
2358
2359 DEBUG(" PAIR %p (%s%s%s %s %s%s%s) %s%s", child,
2360 lhs_quote, cp->attr, lhs_quote,
2361 fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"),
2362 rhs_quote, cp->value, rhs_quote,
2363 in_ident1, in_ident2);
2364 }
2365 break;
2366
2367 case CONF_ITEM_DATA:
2368 {
2369 CONF_DATA const *cd = cf_item_to_data(child);
2370
2371 DEBUG(" DATA %p (%s *)%s = %p %s%s", child,
2372 cd->type, cd->name ? cd->name : "", cd->data,
2373 in_ident1, in_ident2);
2374 break;
2375 }
2376
2377 default:
2378 DEBUG(" INVALID - %p", child);
2379 break;
2380 }
2381 }
2382}
2383
2384/** Ease of use from debugger
2385 */
2387{
2388 cf_item_debug(cp);
2389}
2390
2391/** Ease of use from debugger
2392 */
2394{
2395 cf_item_debug(cs);
2396}
2397
2398/*
2399 * Used when we don't need the children any more, as with
2400 *
2401 * if (0) { ... }
2402 */
2404{
2405 CONF_ITEM *child = NULL;
2406
2407 while ((child = fr_dlist_next(&ci->children, child)) != NULL) {
2408 if (child->type == CONF_ITEM_DATA) {
2409 continue;
2410 }
2411
2412 child = fr_dlist_talloc_free_item(&ci->children, child);
2413 }
2414}
2415
2416void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
2417{
2418 char *spaces, *text;
2419
2420 fr_canonicalize_error(ci, &spaces, &text, slen, str);
2421
2422 cf_log_err(ci, "%s", msg);
2423 cf_log_err(ci, "%s", text);
2424 cf_log_perr(ci, "%s^", spaces);
2425
2427 talloc_free(text);
2428}
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
int const char int line
Definition acutest.h:702
va_start(args, fmt)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:485
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition build.h:121
#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:112
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)
Definition cf_file.c:188
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:1503
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:605
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:694
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:600
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:619
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:428
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:599
fr_rb_node_t ident2_node
Entry in the ident2 tree.
Definition cf_priv.h:51
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:102
CONF_ITEM * parent
Parent.
Definition cf_priv.h:56
fr_token_t name2_quote
The type of quoting around name2.
Definition cf_priv.h:107
void * base
Definition cf_priv.h:113
char const * name2
Second name token. Given foo bar {} would be bar.
Definition cf_priv.h:105
int argc
number of additional arguments
Definition cf_priv.h:109
char const * attr
Attribute name.
Definition cf_priv.h:73
char const * name
Additional qualification of type.
Definition cf_priv.h:129
#define cf_item_foreach_prev(_ci, _iter, _prev)
Iterate over the contents of a list in reverse order.
Definition cf_priv.h:170
fr_rb_tree_t * ident2
Tree to store the second identifier (name2 || name).
Definition cf_priv.h:59
fr_token_t rhs_quote
Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition cf_priv.h:78
int depth
Definition cf_priv.h:114
char const * value
Attribute value.
Definition cf_priv.h:74
#define cf_item_foreach(_ci, _iter)
Iterate over the contents of a list.
Definition cf_priv.h:150
char const * name1
First name token. Given foo bar {} would be foo.
Definition cf_priv.h:104
void const * data
User data.
Definition cf_priv.h:131
static bool cf_item_has_no_children(CONF_ITEM const *ci)
Check if the CONF_ITEM has no children.
Definition cf_priv.h:180
fr_dlist_head_t children
The head of the ordered list of children.
Definition cf_priv.h:54
fr_token_t * argv_quote
Definition cf_priv.h:111
fr_token_t op
Operator e.g. =, :=.
Definition cf_priv.h:76
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:71
bool pass2
do expansion in pass2.
Definition cf_priv.h:80
char const * filename
The file the config item was parsed from.
Definition cf_priv.h:64
fr_rb_tree_t * ident1
Tree to store the first identifier (name1 || type || attr).
Definition cf_priv.h:58
bool is_talloced
If true we can do extra checks.
Definition cf_priv.h:132
CONF_SECTION * template
Definition cf_priv.h:119
fr_rb_node_t ident1_node
Entry in the ident1 tree.
Definition cf_priv.h:50
#define cf_item_foreach_next(_ci, _iter, _prev)
Iterate over the contents of a list.
Definition cf_priv.h:160
@ 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
enum conf_type CONF_ITEM_TYPE
char const ** argv
additional arguments
Definition cf_priv.h:110
char const * type
C type of data being stored.
Definition cf_priv.h:128
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:126
bool parsed
Was this item used during parsing?
Definition cf_priv.h:81
fr_token_t lhs_quote
Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition cf_priv.h:77
bool free
If true, free data with talloc if parent node is freed.
Definition cf_priv.h:133
int lineno
The line number the config item began on.
Definition cf_priv.h:63
CONF_ITEM_TYPE type
Whether the config item is a config_pair, conf_section or cf_data.
Definition cf_priv.h:61
Internal data that is associated with a configuration section.
Definition cf_priv.h:125
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:631
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:539
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition cf_util.c:1610
void * _cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd)
Remove data from a configuration section.
Definition cf_util.c:1859
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:1095
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:1884
unsigned int cf_pair_count_descendents(CONF_SECTION const *cs)
Count the number of conf pairs beneath a section.
Definition cf_util.c:1492
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:1440
void cf_section_debug(CONF_SECTION *cs)
Ease of use from debugger.
Definition cf_util.c:2393
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:1731
CONF_ITEM * cf_data_to_item(CONF_DATA const *cd)
Cast CONF_DATA to a CONF_ITEM.
Definition cf_util.c:753
CONF_ITEM * _cf_item_remove(CONF_ITEM *parent, CONF_ITEM *child)
Remove item from parent and fixup trees.
Definition cf_util.c:446
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:1697
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:1247
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:1507
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:1953
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp, bool copy_meta)
Duplicate a CONF_PAIR.
Definition cf_util.c:1308
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:408
static int8_t _cf_ident1_cmp(void const *a, void const *b)
Compare the first identifier of a child.
Definition cf_util.c:259
#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:1657
fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep)
Concatenate the values of any pairs with name attr.
Definition cf_util.c:1527
void cf_item_free_children(CONF_ITEM *ci)
Definition cf_util.c:2403
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
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:1138
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:2032
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1750
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:737
static int8_t _cf_ident2_cmp(void const *a, void const *b)
Compare the first and second identifiers of a child.
Definition cf_util.c:366
static int8_t cf_ident2_cmp(void const *a, void const *b)
Compare only the second identifier of a child.
Definition cf_util.c:316
CONF_ITEM * _cf_parent(CONF_ITEM const *ci)
Return the parent of a CONF_ITEM.
Definition cf_util.c:575
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:1266
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:2055
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:996
void cf_pair_mark_parsed(CONF_PAIR *cp)
Mark a pair as parsed.
Definition cf_util.c:1363
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
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:786
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:509
static void _pair_count(int *count, CONF_SECTION const *cs)
Callback to determine the number of pairs in a section.
Definition cf_util.c:1473
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:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
CONF_ITEM * _cf_item_prev(CONF_ITEM const *ci, CONF_ITEM const *curr)
Return the next child of cs.
Definition cf_util.c:524
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:1426
CONF_DATA * cf_item_to_data(CONF_ITEM const *ci)
Cast CONF_ITEM to CONF_DATA performing a type check.
Definition cf_util.c:703
void _cf_filename_set(CONF_ITEM *ci, char const *filename)
Set the filename of a CONF_ITEM.
Definition cf_util.c:893
char const * cf_section_value_find(CONF_SECTION const *cs, char const *attr)
Find a pair in a CONF_SECTION.
Definition cf_util.c:1119
CONF_SECTION * _cf_root(CONF_ITEM const *ci)
Return the top level CONF_SECTION holding all other CONF_ITEM.
Definition cf_util.c:557
void _cf_lineno_set(CONF_ITEM *ci, int lineno)
Set the line number of a CONF_ITEM.
Definition cf_util.c:905
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:2206
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:2144
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:1815
static int _cd_free(CONF_DATA *cd)
Free user data associated with CONF_DATA.
Definition cf_util.c:1635
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:1993
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:2237
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:47
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition cf_util.c:1196
char const * _cf_filename(CONF_ITEM const *ci)
Return the filename the CONF_ITEM was parsed in.
Definition cf_util.c:603
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
Definition cf_util.c:645
void _cf_item_debug(CONF_ITEM const *ci)
Print out debugging information about a CONFIG_ITEM.
Definition cf_util.c:2261
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1595
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
Definition cf_util.c:1375
#define IS_WILDCARD(_ident)
Definition cf_util.c:75
static CONF_ITEM * cf_prev(CONF_ITEM const *parent, CONF_ITEM const *current, CONF_ITEM_TYPE type)
Return the previos child that's of the specified type.
Definition cf_util.c:66
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1625
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:2167
CONF_PAIR * cf_pair_first(CONF_SECTION const *cs)
Return the first child that's a CONF_PAIR.
Definition cf_util.c:1387
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:88
static void truncate_filename(char const **e, char const **p, int *len, char const *filename)
Definition cf_util.c:1912
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:1400
void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
Definition cf_util.c:2416
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:1071
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:1715
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:175
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
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:927
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:1454
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
Return variadic argument at the specified index.
Definition cf_util.c:1212
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:1413
int _cf_lineno(CONF_ITEM const *ci)
Return the lineno the CONF_ITEM was parsed at.
Definition cf_util.c:589
static int _cf_section_free(CONF_SECTION *cs)
Free a section and associated trees.
Definition cf_util.c:765
CONF_SECTION * cf_section_first(CONF_SECTION const *cs)
Return the first child in a CONF_SECTION.
Definition cf_util.c:983
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
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:1048
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
Definition cf_util.c:1229
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair in a given section with a new pair, of the given value.
Definition cf_util.c:1337
void _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child)
Add a child.
Definition cf_util.c:381
void cf_pair_debug(CONF_PAIR *cp)
Ease of use from debugger.
Definition cf_util.c:2386
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition cf_util.c:721
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:1009
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1565
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:1773
#define cf_item_add(_parent, _child)
Definition cf_util.h:83
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:286
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:241
#define cf_lineno_set(_ci, _lineno)
Definition cf_util.h:131
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_item_remove(_parent, _child)
Definition cf_util.h:89
#define cf_item_next(_parent, _curr)
Definition cf_util.h:92
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:293
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#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_filename_set(_ci, _filename)
Definition cf_util.h:128
#define cf_item_debug(_cf)
Definition cf_util.h:358
int(* cf_walker_t)(void *data, void *ctx)
Definition cf_util.h:76
#define CF_IDENT_ANY
Definition cf_util.h:78
static fr_atomic_queue_t * aq
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:208
#define MEM(x)
Definition debug.h:36
static char const * spaces
Definition dependency.c:360
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
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:260
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:638
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:588
static void * fr_dlist_talloc_free_item(fr_dlist_head_t *list_head, void *ptr)
Free the item specified.
Definition dlist.h:876
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:378
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:555
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:414
#define LOG_DST
Definition network.c:29
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition log.h:260
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition log.h:257
talloc_free(reap)
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition log.c:313
void fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
Drain any outstanding messages from the fr_strerror buffers.
Definition log.c:608
void fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, va_list ap)
Send a server log message to its destination.
Definition log.c:341
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:87
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition log.c:577
char const * first_prefix
Prefix for the first line printed.
Definition log.h:125
char const * subsq_prefix
Prefix for subsequent lines.
Definition log.h:126
fr_log_type_t
Definition log.h:54
@ L_INFO
Informational message.
Definition log.h:55
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:851
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:874
#define fr_assert(_expr)
Definition rad_assert.h:38
static rc_request_t * current
static bool done
Definition radclient.c:81
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
Definition rb.c:781
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition rb.c:824
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
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:722
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:271
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:321
static char const * name
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1459
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
Definition sbuff.c:1617
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF(_sbuff_or_marker)
return count
Definition module.c:155
fr_aka_sim_id_type_t type
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
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:558
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:650
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:467
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
Definition talloc.c:842
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition talloc.c:682
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:229
const bool fr_assignment_op[T_TOKEN_LAST]
Definition token.c:169
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:34
fr_table_num_sorted_t const fr_token_quotes_table[]
Definition token.c:67
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:199
const bool fr_binary_op[T_TOKEN_LAST]
Definition token.c:217
enum fr_token fr_token_t
@ T_INVALID
Definition token.h:39
@ T_BARE_WORD
Definition token.h:120
#define FR_TABLE_NOT_FOUND
Macro to use as dflt.
Definition token.h:137
static fr_slen_t parent
Definition pair.h:841
static fr_slen_t data
Definition value.h:1291
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1023