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: ea78f5049b2c75bbbc4609ea90cc737627a56d3e $
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: ea78f5049b2c75bbbc4609ea90cc737627a56d3e $")
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/** Set the quoting of the name2 identifier
1237 *
1238 * @param[in] cs containing name2.
1239 * @param[in] token the quote token
1240 */
1242{
1243 if (!cs) return;
1244
1245 cs->name2_quote = token;
1246}
1247
1248/** Return the quoting for one of the variadic arguments
1249 *
1250 * @param[in] cs containing the arguments.
1251 * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1252 * @return
1253 * - #T_BARE_WORD.
1254 * - #T_SINGLE_QUOTED_STRING.
1255 * - #T_BACK_QUOTED_STRING.
1256 * - #T_DOUBLE_QUOTED_STRING.
1257 * - #T_INVALID if cs was NULL or the index was invalid.
1258 */
1260{
1261 if (!cs || !cs->argv_quote || (argc < 0) || (argc > cs->argc)) return T_INVALID;
1262
1263 return cs->argv_quote[argc];
1264}
1265
1266/** Allocate a #CONF_PAIR
1267 *
1268 * @param[in] parent #CONF_SECTION to hang this #CONF_PAIR off of.
1269 * @param[in] attr name.
1270 * @param[in] value of #CONF_PAIR.
1271 * @param[in] op #T_OP_EQ, #T_OP_SET etc.
1272 * @param[in] lhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1273 * @param[in] rhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1274 * @return
1275 * - NULL on error.
1276 * - A new #CONF_SECTION parented by parent.
1277 */
1278CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value,
1279 fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
1280{
1281 CONF_PAIR *cp;
1282
1284 if (!attr) return NULL;
1285
1286 cp = talloc_zero(parent, CONF_PAIR);
1287 if (!cp) return NULL;
1288
1290
1291 cp->lhs_quote = lhs_quote;
1292 cp->rhs_quote = rhs_quote;
1293 cp->op = op;
1294
1295 cp->attr = talloc_typed_strdup(cp, attr);
1296 if (!cp->attr) {
1297 error:
1298 talloc_free(cp);
1299 return NULL;
1300 }
1301
1302 if (value) {
1303 cp->value = talloc_typed_strdup(cp, value);
1304 if (!cp->value) goto error;
1305 }
1306
1307 cf_item_add(parent, &(cp->item));
1308 return cp;
1309}
1310
1311/** Duplicate a #CONF_PAIR
1312 *
1313 * @param parent to allocate new pair in.
1314 * @param cp to duplicate.
1315 * @param copy_meta Copy additional meta data for a pair
1316 * @return
1317 * - NULL on error.
1318 * - A duplicate of the input pair.
1319 */
1321{
1322 CONF_PAIR *new;
1323
1325 fr_assert(cp);
1326
1327 new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), cp->op, cp->lhs_quote, cp->rhs_quote);
1328 if (!new) return NULL;
1329
1330 if (copy_meta) new->parsed = cp->parsed;
1331 cf_lineno_set(new, cp->item.lineno);
1332 cf_filename_set(new, cp->item.filename);
1333
1334 return new;
1335}
1336
1337/** Replace pair in a given section with a new pair, of the given value.
1338 *
1339 * @note A new pair with the same metadata as the #CONF_PAIR will be added
1340 * even if the #CONF_PAIR can't be found inside the #CONF_SECTION.
1341 *
1342 * @param[in] cs to replace pair in.
1343 * @param[in] cp to replace.
1344 * @param[in] value New value to assign to cp.
1345 * @return
1346 * - 0 on success.
1347 * - -1 on failure.
1348 */
1350{
1351 CONF_PAIR *new_cp;
1352
1353 if (!cs || !cp || !value) return -1;
1354
1355 /*
1356 * Remove the old CONF_PAIR
1357 */
1358 (void)cf_item_remove(cs, cp);
1359
1360 /*
1361 * Add the new CONF_PAIR
1362 */
1363 MEM(new_cp = cf_pair_dup(cs, cp, true));
1365 MEM(cp->value = talloc_typed_strdup(cp, value));
1366
1367 return 0;
1368}
1369
1370
1371/** Mark a pair as parsed
1372 *
1373 * @param[in] cp to mark as parsed.
1374 */
1376{
1377 cp->parsed = true;
1378}
1379
1380/** Return whether a pair has already been parsed
1381 *
1382 * @param[in] cp to check.
1383 * @return
1384 * - true if pair has been parsed.
1385 * - false if the pair hasn't been parsed.
1386 */
1388{
1389 return cp->parsed;
1390}
1391
1392/** Return the first child that's a #CONF_PAIR
1393 *
1394 * @param[in] cs to return children from.
1395 * @return
1396 * - The first #CONF_ITEM that's a child of cs and a CONF_PAIR.
1397 * - NULL if no #CONF_ITEM matches that criteria.
1398 */
1403
1404/** Return the next child that's a #CONF_PAIR
1405 *
1406 * @param[in] cs to return children from.
1407 * @param[in] curr child to start searching from.
1408 * @return
1409 * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1410 * - NULL if no #CONF_ITEM matches that criteria.
1411 */
1416
1417/** Return the previous child that's a #CONF_PAIR
1418 *
1419 * @param[in] cs to return children from.
1420 * @param[in] curr child to start searching from.
1421 * @return
1422 * - The previous #CONF_ITEM that's a child of cs and a CONF_PAIR.
1423 * - NULL if no #CONF_ITEM matches that criteria.
1424 */
1429
1430/** Search for a #CONF_PAIR with a specific name
1431 *
1432 * @param[in] cs to search in.
1433 * @param[in] attr to find.
1434 * @return
1435 * - The next matching #CONF_PAIR.
1436 * - NULL if none matched.
1437 */
1438CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *attr)
1439{
1440 return cf_item_to_pair(cf_find(cf_section_to_item(cs), CONF_ITEM_PAIR, attr, NULL));
1441}
1442
1443/** Find a pair with a name matching attr, after specified pair
1444 *
1445 * @param[in] cs to search in.
1446 * @param[in] prev Pair to search from (may be NULL).
1447 * @param[in] attr to find (may be NULL in which case any attribute matches).
1448 * @return
1449 * - The next matching #CONF_PAIR
1450 * - NULL if none matched.
1451 */
1452CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
1453{
1455}
1456
1457/** Find a pair with a name matching attr in the specified section or one of its parents
1458 *
1459 * @param[in] cs to search in. Will start in the current section
1460 * and work upwards.
1461 * @param[in] attr to find.
1462 * @return
1463 * - A matching #CONF_PAIR.
1464 * - NULL if none matched.
1465 */
1466CONF_PAIR *cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
1467{
1468 CONF_ITEM const *parent = cf_section_to_item(cs);
1469
1470 do {
1471 CONF_ITEM *found;
1472
1473 found = cf_find(parent, CONF_ITEM_PAIR, attr, NULL);
1474 if (found) return cf_item_to_pair(found);
1475 } while ((parent = cf_parent(parent)));
1476
1477 return NULL;
1478}
1479
1480/** Callback to determine the number of pairs in a section
1481 *
1482 * @param[out] count Where we store the number of pairs found.
1483 * @param[in] cs we're currently searching in.
1484 */
1485static void _pair_count(int *count, CONF_SECTION const *cs)
1486{
1487 CONF_ITEM const *ci = NULL;
1488
1489 while ((ci = cf_item_next(cs, ci))) {
1490 if (cf_item_is_section(ci)) {
1492 continue;
1493 }
1494
1495 (*count)++;
1496 }
1497}
1498
1499/** Count the number of conf pairs beneath a section
1500 *
1501 * @param[in] cs to search for items in.
1502 * @return The number of pairs nested within section.
1503 */
1505{
1506 int count = 0;
1507
1508 _pair_count(&count, cs);
1509
1510 return count;
1511}
1512
1513/** Count the number of times an attribute occurs in a parent section
1514 *
1515 * @param[in] cs to search for items in.
1516 * @param[in] attr to search for.
1517 * @return The number of pairs of that attribute type.
1518 */
1519unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
1520{
1521 size_t i;
1522 CONF_PAIR *cp = NULL;
1523
1524 for (i = 0; (cp = cf_pair_find_next(cs, cp, attr)); i++);
1525
1526 return i;
1527}
1528
1529/** Concatenate the values of any pairs with name attr
1530 *
1531 * @param[out] out where to write the concatenated values.
1532 * @param[in] cs to search in.
1533 * @param[in] attr to search for.
1534 * @param[in] sep to use to separate values
1535 * @return
1536 * - Length of the data written to out on success.
1537 * - < 0 on failure. Number of additional bytes required in buffer.
1538 */
1539fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep)
1540{
1541 fr_sbuff_t our_out = FR_SBUFF(out);
1542 CONF_PAIR *cp;
1543 fr_slen_t slen = 0;
1544 fr_sbuff_escape_rules_t e_rules = {
1545 .name = __FUNCTION__,
1546 .chr = '\\'
1547 };
1548
1549 if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
1550
1551 for (cp = cf_pair_find(cs, attr); cp;) {
1552 slen = fr_sbuff_in_escape(&our_out, cf_pair_value(cp),
1553 strlen(cf_pair_value(cp)), &e_rules);
1554 if (slen < 0) return slen;
1555
1556 cp = cf_pair_find_next(cs, cp, attr);
1557 if (cp && sep) {
1558 slen = fr_sbuff_in_strcpy(&our_out, sep);
1559 if (slen < 0) return slen;
1560 }
1561 }
1562
1563 FR_SBUFF_SET_RETURN(out, &our_out);
1564}
1565
1566/** Return the attr of a #CONF_PAIR
1567 *
1568 * Return the LHS value of a pair (the attribute).
1569 *
1570 * @param[in] pair to return the attribute for.
1571 * @return
1572 * - NULL if the pair was NULL.
1573 * - The attribute name of the pair.
1574 *
1575 * @hidecallergraph
1576 */
1577char const *cf_pair_attr(CONF_PAIR const *pair)
1578{
1579 return (pair ? pair->attr : NULL);
1580}
1581
1582/** Return the value of a #CONF_PAIR
1583 *
1584 * Return the RHS value of a pair (the value).
1585 *
1586 * @param[in] pair to return the value of.
1587 * @return
1588 * - NULL if pair was NULL or the pair has no value.
1589 * - The string value of the pair.
1590 *
1591 * @hidecallergraph
1592 */
1593char const *cf_pair_value(CONF_PAIR const *pair)
1594{
1595 return (pair ? pair->value : NULL);
1596}
1597
1598/** Return the operator of a pair
1599 *
1600 * @param[in] pair to return the operator of.
1601 * @return
1602 * - T_INVALID if pair was NULL.
1603 * - T_OP_* (one of the operator constants).
1604 *
1605 * @hidecallergraph
1606 */
1608{
1609 return (pair ? pair->op : T_INVALID);
1610}
1611
1612/** Return the value (lhs) quoting of a pair
1613 *
1614 * @param pair to extract value type from.
1615 * @return
1616 * - #T_BARE_WORD.
1617 * - #T_SINGLE_QUOTED_STRING.
1618 * - #T_BACK_QUOTED_STRING.
1619 * - #T_DOUBLE_QUOTED_STRING.
1620 * - #T_INVALID if the pair is NULL.
1621 */
1623{
1624 return (pair ? pair->lhs_quote : T_INVALID);
1625}
1626
1627/** Return the value (rhs) quoting of a pair
1628 *
1629 * @param pair to extract value type from.
1630 * @return
1631 * - #T_BARE_WORD.
1632 * - #T_SINGLE_QUOTED_STRING.
1633 * - #T_BACK_QUOTED_STRING.
1634 * - #T_DOUBLE_QUOTED_STRING.
1635 * - #T_INVALID if the pair is NULL.
1636 */
1638{
1639 return (pair ? pair->rhs_quote : T_INVALID);
1640}
1641
1642/** Free user data associated with #CONF_DATA
1643 *
1644 * @param[in] cd being freed.
1645 * @return 0
1646 */
1647static int _cd_free(CONF_DATA *cd)
1648{
1649 void *to_free;
1650
1651 memcpy(&to_free, &cd->data, sizeof(to_free));
1652
1653 if (cd->free) talloc_decrease_ref_count(to_free); /* Also works OK for non-reference counted chunks */
1654
1655 return 0;
1656}
1657
1658/** Allocate a new user data container
1659 *
1660 * @param[in] parent #CONF_PAIR, or #CONF_SECTION to hang CONF_DATA off of.
1661 * @param[in] data being added.
1662 * @param[in] type of data being added.
1663 * @param[in] name String identifier of the user data.
1664 * @param[in] do_free function, called when the parent #CONF_SECTION is being freed.
1665 * @return
1666 * - CONF_DATA on success.
1667 * - NULL on error.
1668 */
1669static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
1670{
1671 CONF_DATA *cd;
1672
1673 cd = talloc_zero(parent, CONF_DATA);
1674 if (!cd) return NULL;
1675
1677
1678 /*
1679 * strdup so if the data is freed, we can
1680 * still remove it from the section without
1681 * explosions.
1682 */
1683 if (data) {
1684 cd->type = talloc_typed_strdup(cd, type);
1685 cd->data = data;
1686 }
1687 if (name) cd->name = talloc_typed_strdup(cd, name);
1688
1689 if (do_free) {
1690 cd->free = true;
1691 talloc_set_destructor(cd, _cd_free);
1692 }
1693
1694 cf_item_add(parent, cd);
1695 return cd;
1696}
1697
1698/** Find user data in a config section
1699 *
1700 * @param[in] ci The section to search for data in.
1701 * @param[in] type of user data. Used for name spacing and walking over a specific
1702 * type of user data.
1703 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1704 * may be used to match on type only.
1705 * @return
1706 * - The user data.
1707 * - NULL if no user data exists.
1708 */
1709CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
1710{
1712}
1713
1714/** Return the next item of user data
1715 *
1716 * @param[in] ci The section to search for data in.
1717 * @param[in] prev section we found. May be NULL in which case
1718 * we just return the next section after prev.
1719 * @param[in] type of user data. Used for name spacing and walking over a specific
1720 * type of user data.
1721 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1722 * can be used to match any name2 value.
1723 * @return
1724 * - The next matching #CONF_DATA.
1725 * - NULL if there is no more matching #CONF_DATA.
1726 */
1727CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
1728{
1730}
1731
1732/** Find matching data in the specified section or one of its parents
1733 *
1734 * @param[in] ci The section to search for data in.
1735 * @param[in] type of user data. Used for name spacing and walking over a specific
1736 * type of user data.
1737 * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1738 * may be used to match on type only.
1739 * @return
1740 * - The next matching #CONF_DATA.
1741 * - NULL if there is no more matching #CONF_DATA.
1742 */
1743CONF_DATA *_cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
1744{
1745 CONF_ITEM const *parent = ci;
1746
1747 do {
1748 CONF_ITEM *found;
1749
1751 if (found) return cf_item_to_data(found);
1752 } while ((parent = cf_parent(parent)));
1753
1754 return NULL;
1755}
1756
1757/** Return the user assigned value of #CONF_DATA
1758 *
1759 * @param[in] cd to return value of.
1760 * @return the user data stored within the #CONF_DATA.
1761 */
1762void *cf_data_value(CONF_DATA const *cd)
1763{
1764 void *to_return;
1765
1766 if (!cd) return NULL;
1767
1768 memcpy(&to_return, &cd->data, sizeof(to_return));
1769
1770 return to_return;
1771}
1772
1773/** Add talloced user data to a config section
1774 *
1775 * @param[in] ci to add data to.
1776 * @param[in] data to add.
1777 * @param[in] name String identifier of the user data.
1778 * @param[in] do_free Function to free user data when the CONF_SECTION is freed.
1779 * @param[in] filename Source file the #CONF_DATA was added in.
1780 * @param[in] lineno the #CONF_DATA was added at.
1781 * @return
1782 * - #CONF_DATA - opaque handle to the stored data - on success.
1783 * - NULL error.
1784 */
1785CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free,
1786 char const *filename, int lineno)
1787{
1788 CONF_DATA *cd;
1789 CONF_DATA const *found;
1790 char const *type = NULL;
1791
1792 if (!ci) return NULL;
1793
1794 if (data) type = talloc_get_name(data);
1795
1796 /*
1797 * Already exists. Can't add it.
1798 */
1799 found = _cf_data_find(ci, type, name);
1800 if (found) {
1801 return NULL;
1802 }
1803
1804 cd = cf_data_alloc(ci, data, type, name, do_free);
1805 if (!cd) {
1806 cf_log_err(ci, "Failed allocating data");
1807 return NULL;
1808 }
1809 cd->is_talloced = true;
1810 cf_filename_set(cd, filename);
1811 cf_lineno_set(cd, lineno);
1812
1813 return cd;
1814}
1815
1816/** Add non-talloced user data to a config section
1817 *
1818 * @param[in] ci to add data to.
1819 * @param[in] data to add.
1820 * @param[in] type identifier of the user data.
1821 * @param[in] name String identifier of the user data.
1822 * @param[in] filename Source file the #CONF_DATA was added in.
1823 * @param[in] lineno the #CONF_DATA was added at.
1824 * - #CONF_DATA - opaque handle to the stored data - on success.
1825 * - NULL error.
1826 */
1827CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name,
1828 char const *filename, int lineno)
1829{
1830 CONF_DATA *cd;
1831 CONF_DATA const *found;
1832
1833 /*
1834 * Already exists. Can't add it.
1835 */
1836 found = _cf_data_find(ci, type, name);
1837 if (found) {
1838 /*
1839 * Suppress these, as it's OK for the conf_parser_t in main_config.c
1840 */
1841 if (strcmp(type, "conf_parser_t") == 0) return NULL;
1842
1843 cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type,
1844 name, found->item.filename, found->item.lineno);
1845 return NULL;
1846 }
1847
1848 cd = cf_data_alloc(ci, data, type, name, false);
1849 if (!cd) {
1850 cf_log_err(ci, "Failed allocating data");
1851 return NULL;
1852 }
1853 cd->is_talloced = false;
1854 cf_filename_set(cd, filename);
1855 cf_lineno_set(cd, lineno);
1856
1857 return cd;
1858}
1859
1860/** Remove data from a configuration section
1861 *
1862 * @note If cd was not found it will not be freed, and it is the caller's responsibility
1863 * to free it explicitly, or free the section it belongs to.
1864 *
1865 * @param[in] parent to remove data from.
1866 * @param[in] cd opaque handle of the stored data.
1867 * @return
1868 * - The value stored within the data (if cd is valid and was found and removed).
1869 * - NULL if not found.
1870 */
1872{
1873 void *data;
1874
1875 if (!cd) return NULL;
1876
1877 (void)cf_item_remove(parent, cd);
1878
1879 talloc_set_destructor(cd, NULL); /* Disarm the destructor */
1880 memcpy(&data, &cd->data, sizeof(data));
1882
1883 return data;
1884}
1885
1886/** Walk over a specific type of CONF_DATA
1887 *
1888 * @param[in] ci containing the CONF_DATA to walk over.
1889 * @param[in] type of CONF_DATA to walk over.
1890 * @param[in] cb to call when we find CONF_DATA of the specified type.
1891 * @param[in] ctx to pass to cb.
1892 * @return
1893 * - 0 on success.
1894 * - -1 on failure.
1895 */
1896int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
1897{
1898 CONF_DATA *cd;
1900 int ret = 0;
1901
1902 if (!ci->ident2) return 0;
1903
1904 for (ci = fr_rb_iter_init_inorder(&iter, ci->ident2);
1905 ci;
1906 ci = fr_rb_iter_next_inorder(&iter)) {
1907 /*
1908 * We're walking ident2, not all of the items will be data
1909 */
1910 if (ci->type != CONF_ITEM_DATA) continue;
1911
1912 cd = (void *) ci;
1913 if ((cd->type != type) && (strcmp(cd->type, type) != 0)) continue;
1914
1915 ret = cb(UNCONST(void *, cd->data), ctx);
1916 if (ret) {
1917 break;
1918 }
1919 }
1920
1921 return ret;
1922}
1923
1924static inline CC_HINT(nonnull) void truncate_filename(char const **e, char const **p, int *len, char const *filename)
1925{
1926 size_t flen;
1927 char const *q;
1928
1929 #define FILENAME_TRUNCATE 60
1930
1931 *p = filename;
1932 *e = "";
1933
1934 flen = talloc_array_length(filename) - 1;
1935 if (flen <= FILENAME_TRUNCATE) {
1936 *len = (int)flen;
1937 return;
1938 }
1939
1940 *p += flen - FILENAME_TRUNCATE;
1941 *len = FILENAME_TRUNCATE;
1942
1943 q = strchr(*p, FR_DIR_SEP);
1944 if (q) {
1945 q++;
1946 *p += (q - *p);
1947 *len -= (q - *p);
1948 }
1949
1950 *e = "...";
1951}
1952
1953/** Check to see if the CONF_PAIR value is present in the specified table
1954 *
1955 * If it's not present, return an error and produce a helpful log message
1956 *
1957 * @param[out] out The result of parsing the pair value.
1958 * @param[in] table to look for string values in.
1959 * @param[in] table_len Length of the table.
1960 * @param[in] cp to parse.
1961 * @return
1962 * - 0 on success.
1963 * - -1 on failure.
1964 */
1965int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
1966{
1967 char *list = NULL;
1968 int32_t res;
1969 size_t i;
1970
1972 if (res != FR_TABLE_NOT_FOUND) {
1973 *out = res;
1974 return 0;
1975 }
1976
1977 for (i = 0; i < table_len; i++) MEM(list = talloc_asprintf_append_buffer(list, "'%s', ", table[i].name.str));
1978
1979 if (!list) {
1980 cf_log_err(cp, "Internal error parsing %s: Table was empty", cf_pair_attr(cp));
1981 return -1;
1982 }
1983
1984 /*
1985 * Trim the final ", "
1986 */
1987 MEM(list = talloc_bstr_realloc(NULL, list, talloc_array_length(list) - 3));
1988
1989 cf_log_err(cp, "Invalid value \"%s\". Expected one of %s", cf_pair_value(cp), list);
1990
1991 talloc_free(list);
1992
1993 return -1;
1994}
1995
1996/** Log an error message relating to a #CONF_ITEM
1997 *
1998 * @param[in] type of log message.
1999 * @param[in] ci #CONF_ITEM to print file/lineno for.
2000 * @param[in] file src file the log message was generated in.
2001 * @param[in] line number the log message was generated on.
2002 * @param[in] fmt of the message.
2003 * @param[in] ap Message args.
2004 */
2005void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
2006{
2007 va_list aq;
2008
2009 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2010
2011 if (!ci || !ci->filename || !*ci->filename || (*ci->filename == '<') ||
2012 (((type == L_DBG) || (type == L_INFO)) && !DEBUG_ENABLED4)) {
2013 va_copy(aq, ap);
2015 va_end(aq);
2016 return;
2017 }
2018
2019 {
2020 char const *e, *p;
2021 int len;
2022 char *msg;
2023
2024 truncate_filename(&e, &p, &len, ci->filename);
2025
2026 va_copy(aq, ap);
2027 msg = fr_vasprintf(NULL, fmt, aq);
2028 va_end(aq);
2029
2030 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2032 }
2033}
2034
2035/** Log an error message relating to a #CONF_ITEM
2036 *
2037 * @param[in] type of log message.
2038 * @param[in] file src file the log message was generated in.
2039 * @param[in] line number the log message was generated on.
2040 * @param[in] ci #CONF_ITEM to print file/lineno for.
2041 * @param[in] fmt of the message.
2042 * @param[in] ... Message args.
2043 */
2044void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2045{
2046 va_list ap;
2047
2048 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2049
2050 va_start(ap, fmt);
2051 _cf_vlog(type, ci, file, line, fmt, ap);
2052 va_end(ap);
2053}
2054
2055/** Log an error message relating to a #CONF_ITEM
2056 *
2057 * Drains the fr_strerror() stack emitting one or more error messages.
2058 *
2059 * @param[in] type of log message.
2060 * @param[in] file src file the log message was generated in.
2061 * @param[in] line number the log message was generated on.
2062 * @param[in] ci #CONF_ITEM to print file/lineno for.
2063 * @param[in] f_rules Additional optional formatting controls.
2064 * @param[in] fmt of the message.
2065 * @param[in] ap Message args.
2066 */
2067void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2068 fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
2069{
2070 va_list aq;
2071
2072 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2073
2074 if (!ci || !ci->filename) {
2075 va_copy(aq, ap);
2076 fr_vlog_perror(LOG_DST, type, file, line, f_rules, fmt, aq);
2077 va_end(aq);
2078 return;
2079 }
2080
2081 {
2082 char const *e, *p;
2083 int len;
2084 char *prefix;
2085 TALLOC_CTX *thread_log_pool;
2086 TALLOC_CTX *pool;
2087 fr_log_perror_format_t our_f_rules;
2088
2089 if (f_rules) {
2090 our_f_rules = *f_rules;
2091 } else {
2092 our_f_rules = (fr_log_perror_format_t){};
2093 }
2094
2095 /*
2096 * Get some scratch space from the logging code
2097 */
2098 thread_log_pool = fr_log_pool_init();
2099 pool = talloc_new(thread_log_pool);
2100
2101 truncate_filename(&e, &p, &len, ci->filename);
2102
2103 /*
2104 * Create the file location string
2105 */
2106 prefix = fr_asprintf(pool, "%s%.*s[%d]: ", e, len, p, ci->lineno);
2107
2108 /*
2109 * Prepend it to an existing first prefix
2110 */
2111 if (f_rules && f_rules->first_prefix) {
2112 char *first;
2113
2114 first = talloc_bstrdup(pool, prefix);
2115 talloc_buffer_append_buffer(pool, first, f_rules->first_prefix);
2116
2117 our_f_rules.first_prefix = first;
2118 } else {
2119 our_f_rules.first_prefix = prefix;
2120 }
2121
2122 /*
2123 * Prepend it to an existing subsq prefix
2124 */
2125 if (f_rules && f_rules->subsq_prefix) {
2126 char *subsq;
2127
2128 subsq = talloc_bstrdup(pool, prefix);
2129 talloc_buffer_append_buffer(pool, subsq, f_rules->subsq_prefix);
2130
2131 our_f_rules.subsq_prefix = subsq;
2132 } else {
2133 our_f_rules.subsq_prefix = prefix;
2134 }
2135
2136 va_copy(aq, ap);
2137 fr_vlog_perror(LOG_DST, type, file, line, &our_f_rules, fmt, aq);
2138 va_end(aq);
2139
2140 talloc_free(pool);
2141 }
2142}
2143
2144/** Log an error message relating to a #CONF_ITEM
2145 *
2146 * Drains the fr_strerror() stack emitting one or more error messages.
2147 *
2148 * @param[in] type of log message.
2149 * @param[in] file src file the log message was generated in.
2150 * @param[in] line number the log message was generated on.
2151 * @param[in] ci #CONF_ITEM to print file/lineno for.
2152 * @param[in] f_rules Additional optional formatting controls.
2153 * @param[in] fmt of the message.
2154 * @param[in] ... Message args.
2155 */
2156void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2157 fr_log_perror_format_t const *f_rules, char const *fmt, ...)
2158{
2159 va_list ap;
2160
2161 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2162
2163 va_start(ap, fmt);
2164 _cf_vlog_perr(type, ci, file, line, f_rules, fmt, ap);
2165 va_end(ap);
2166}
2167
2168/** Log a debug message relating to a #CONF_ITEM
2169 *
2170 * Always emits a filename/lineno prefix if available
2171 *
2172 * @param[in] type of log message.
2173 * @param[in] file src file the log message was generated in.
2174 * @param[in] line number the log message was generated on.
2175 * @param[in] ci #CONF_ITEM to print file/lineno for.
2176 * @param[in] fmt of the message.
2177 * @param[in] ... Message args.
2178 */
2179void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2180{
2181 va_list ap;
2182
2183 if ((type == L_DBG) && !DEBUG_ENABLED) return;
2184
2185 if (!ci || !ci->filename) {
2186 va_start(ap, fmt);
2187 fr_vlog(LOG_DST, type, file, line, fmt, ap);
2188 va_end(ap);
2189 return;
2190 }
2191
2192 {
2193 char const *e, *p;
2194 int len;
2195 char *msg;
2196
2197 truncate_filename(&e, &p, &len, ci->filename);
2198
2199 va_start(ap, fmt);
2200 msg = fr_vasprintf(NULL, fmt, ap);
2201 va_end(ap);
2202
2203 fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2205 }
2206}
2207
2208/** Log an error message in the context of a child pair of the specified parent
2209 *
2210 * @param[in] parent containing the pair.
2211 * @param[in] child name to use as a logging context.
2212 * @param[in] type of log message.
2213 * @param[in] file src file the log message was generated in.
2214 * @param[in] line number the log message was generated on.
2215 * @param[in] fmt of the message.
2216 * @param[in] ... Message args.
2217 */
2219 char const *file, int line, char const *fmt, ...)
2220{
2221 va_list ap;
2222 CONF_PAIR const *cp;
2223
2224 cp = cf_pair_find(parent, child);
2225 if (cp) {
2226 va_start(ap, fmt);
2227 _cf_vlog(type, CF_TO_ITEM(cp), file, line, fmt, ap);
2228 va_end(ap);
2229 return;
2230 }
2231
2232 va_start(ap, fmt);
2234 va_end(ap);
2235}
2236
2237
2238/** Log an error message in the context of a child pair of the specified parent
2239 *
2240 * @param[in] parent containing the pair.
2241 * @param[in] child name to use as a logging context.
2242 * @param[in] type of log message.
2243 * @param[in] file src file the log message was generated in.
2244 * @param[in] line number the log message was generated on.
2245 * @param[in] f_rules Line prefixes.
2246 * @param[in] fmt of the message.
2247 * @param[in] ... Message args.
2248 */
2250 char const *file, int line, fr_log_perror_format_t const *f_rules,
2251 char const *fmt, ...)
2252{
2253 va_list ap;
2254 CONF_PAIR const *cp;
2255
2256 cp = cf_pair_find(parent, child);
2257 if (cp) {
2258 va_start(ap, fmt);
2259 _cf_vlog_perr(type, CF_TO_ITEM(cp), file, line, f_rules, fmt, ap);
2260 va_end(ap);
2261 return;
2262 }
2263
2264 va_start(ap, fmt);
2265 _cf_vlog_perr(type, CF_TO_ITEM(parent), file, line, f_rules, fmt, ap);
2266 va_end(ap);
2267}
2268
2269/** Print out debugging information about a CONFIG_ITEM
2270 *
2271 * @param[in] ci being debugged.
2272 */
2274{
2275 /*
2276 * Print summary of the item
2277 */
2278 switch (ci->type) {
2279 case CONF_ITEM_SECTION:
2280 {
2281 CONF_SECTION const *cs = cf_item_to_section(ci);
2282 int i;
2283
2284 DEBUG("SECTION - %p", cs);
2285 DEBUG(" name1 : %s", cs->name1);
2286 DEBUG(" name2 : %s", cs->name2 ? cs->name2 : "<none>");
2287 DEBUG(" name2_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cs->name2_quote, "<INVALID>"));
2288 DEBUG(" argc : %d", cs->argc);
2289
2290 for (i = 0; i < cs->argc; i++) {
2291 char const *quote = fr_table_str_by_value(fr_token_quotes_table, cs->argv_quote[i], "<INVALID>");
2292 DEBUG(" argv[%i] : %s%s%s", i, quote, cs->argv[i], quote);
2293 }
2294 }
2295 break;
2296
2297 case CONF_ITEM_PAIR:
2298 {
2299 CONF_PAIR const *cp = cf_item_to_pair(ci);
2300
2301 DEBUG("PAIR - %p", cp);
2302 DEBUG(" attr : %s", cp->attr);
2303 DEBUG(" value : %s", cp->value);
2304 DEBUG(" operator : %s", fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"));
2305 DEBUG(" lhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>"));
2306 DEBUG(" rhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>"));
2307 DEBUG(" pass2 : %s", cp->pass2 ? "yes" : "no");
2308 DEBUG(" parsed : %s", cp->parsed ? "yes" : "no");
2309 }
2310 break;
2311
2312 case CONF_ITEM_DATA:
2313 {
2314 CONF_DATA const *cd = cf_item_to_data(ci);
2315
2316 DEBUG("DATA - %p", cd);
2317 DEBUG(" type : %s", cd->type);
2318 DEBUG(" name : %s", cd->name);
2319 DEBUG(" data : %p", cd->data);
2320 DEBUG(" free wth prnt : %s", cd->free ? "yes" : "no");
2321 }
2322 break;
2323
2324 default:
2325 DEBUG("INVALID - %p", ci);
2326 return;
2327 }
2328
2329 DEBUG(" filename : %s", ci->filename);
2330 DEBUG(" line : %i", ci->lineno);
2331 if (ci->parent) DEBUG(" next : %p", fr_dlist_next(&ci->parent->children, ci));
2332 DEBUG(" parent : %p", ci->parent);
2333 DEBUG(" children : %s", cf_item_has_no_children(ci) ? "no" : "yes");
2334 DEBUG(" ident1 tree : %p (%u entries)", ci->ident1, ci->ident1 ? fr_rb_num_elements(ci->ident1) : 0);
2335 DEBUG(" ident2 tree : %p (%u entries)", ci->ident2, ci->ident2 ? fr_rb_num_elements(ci->ident2) : 0);
2336
2337 if (cf_item_has_no_children(ci)) return;
2338
2339 /*
2340 * Print summary of the item's children
2341 */
2342 DEBUG("CHILDREN");
2343
2344 cf_item_foreach(ci, child) {
2345 char const *in_ident1, *in_ident2;
2346
2347 in_ident1 = fr_rb_find(ci->ident1, child) == child? "in ident1 " : "";
2348
2349 if (ci->type != CONF_ITEM_SECTION) {
2350 in_ident2 = false;
2351 } else {
2352 in_ident2 = fr_rb_find(ci->ident2, child) == child? "in ident2 " : "";
2353 }
2354
2355 switch (child->type) {
2356 case CONF_ITEM_SECTION:
2357 {
2358 CONF_SECTION const *cs = cf_item_to_section(child);
2359
2360 DEBUG(" SECTION %p (%s %s) %s%s", child, cs->name1, cs->name2 ? cs->name2 : "<none>",
2361 in_ident1, in_ident2);
2362 }
2363 break;
2364
2365 case CONF_ITEM_PAIR:
2366 {
2367 CONF_PAIR const *cp = cf_item_to_pair(child);
2368 char const *lhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>");
2369 char const *rhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>");
2370
2371 DEBUG(" PAIR %p (%s%s%s %s %s%s%s) %s%s", child,
2372 lhs_quote, cp->attr, lhs_quote,
2373 fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"),
2374 rhs_quote, cp->value, rhs_quote,
2375 in_ident1, in_ident2);
2376 }
2377 break;
2378
2379 case CONF_ITEM_DATA:
2380 {
2381 CONF_DATA const *cd = cf_item_to_data(child);
2382
2383 DEBUG(" DATA %p (%s *)%s = %p %s%s", child,
2384 cd->type, cd->name ? cd->name : "", cd->data,
2385 in_ident1, in_ident2);
2386 break;
2387 }
2388
2389 default:
2390 DEBUG(" INVALID - %p", child);
2391 break;
2392 }
2393 }
2394}
2395
2396/** Ease of use from debugger
2397 */
2399{
2400 cf_item_debug(cp);
2401}
2402
2403/** Ease of use from debugger
2404 */
2406{
2407 cf_item_debug(cs);
2408}
2409
2410/*
2411 * Used when we don't need the children any more, as with
2412 *
2413 * if (0) { ... }
2414 */
2416{
2417 CONF_ITEM *child = NULL;
2418
2419 while ((child = fr_dlist_next(&ci->children, child)) != NULL) {
2420 if (child->type == CONF_ITEM_DATA) {
2421 continue;
2422 }
2423
2424 child = fr_dlist_talloc_free_item(&ci->children, child);
2425 }
2426}
2427
2428void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
2429{
2430 char *spaces, *text;
2431
2432 fr_canonicalize_error(ci, &spaces, &text, slen, str);
2433
2434 cf_log_err(ci, "%s", msg);
2435 cf_log_err(ci, "%s", text);
2436 cf_log_perr(ci, "%s^", spaces);
2437
2439 talloc_free(text);
2440}
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:167
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:1462
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:601
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:690
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:596
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:615
@ 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:595
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:128
#define cf_item_foreach_prev(_ci, _iter, _prev)
Iterate over the contents of a list in reverse order.
Definition cf_priv.h:169
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:149
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:130
static bool cf_item_has_no_children(CONF_ITEM const *ci)
Check if the CONF_ITEM has no children.
Definition cf_priv.h:179
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:131
CONF_SECTION * template
Definition cf_priv.h:118
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:159
@ 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:127
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:125
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:132
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:124
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:1622
void * _cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd)
Remove data from a configuration section.
Definition cf_util.c:1871
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:1896
unsigned int cf_pair_count_descendents(CONF_SECTION const *cs)
Count the number of conf pairs beneath a section.
Definition cf_util.c:1504
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:1452
void cf_section_debug(CONF_SECTION *cs)
Ease of use from debugger.
Definition cf_util.c:2405
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:1743
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:1709
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:1259
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:1519
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:1965
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp, bool copy_meta)
Duplicate a CONF_PAIR.
Definition cf_util.c:1320
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:1669
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:1539
void cf_item_free_children(CONF_ITEM *ci)
Definition cf_util.c:2415
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:2044
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1762
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:1278
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:2067
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:1375
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:1485
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:1438
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:2218
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:2156
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:1827
static int _cd_free(CONF_DATA *cd)
Free user data associated with CONF_DATA.
Definition cf_util.c:1647
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:2005
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:2249
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
void cf_section_add_name2_quote(CONF_SECTION *cs, fr_token_t token)
Set the quoting of the name2 identifier.
Definition cf_util.c:1241
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:2273
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1607
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
Definition cf_util.c:1387
#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:1637
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:2179
CONF_PAIR * cf_pair_first(CONF_SECTION const *cs)
Return the first child that's a CONF_PAIR.
Definition cf_util.c:1399
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:1924
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:1412
void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
Definition cf_util.c:2428
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:1727
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:1466
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:1425
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:1593
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:1349
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:2398
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:1577
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:1785
#define cf_item_add(_parent, _child)
Definition cf_util.h:83
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:244
#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:296
#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:361
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:216
#define MEM(x)
Definition debug.h:36
static char const * spaces
Definition dependency.c:370
#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:611
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:580
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:1456
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:1622
#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:532
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:624
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:441
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
Definition talloc.c:816
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition talloc.c:656
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:224
const bool fr_assignment_op[T_TOKEN_LAST]
Definition token.c:167
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:32
fr_table_num_sorted_t const fr_token_quotes_table[]
Definition token.c:65
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:197
const bool fr_binary_op[T_TOKEN_LAST]
Definition token.c:215
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:845
static fr_slen_t data
Definition value.h:1274
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1012