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