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