The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: ad9d3d30eb6c59602522740c5a7900b161406657 $
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  */
24 RCSID("$Id: ad9d3d30eb6c59602522740c5a7900b161406657 $")
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 
35 static inline int8_t cf_ident2_cmp(void const *a, void const *b);
36 static int8_t _cf_ident1_cmp(void const *a, void const *b);
37 static 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  */
66 static 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  */
89 static 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) {
102  case CONF_ITEM_SECTION:
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)) {
139  cf_item_foreach(parent, ci) {
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  */
176 static 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) {
193  case CONF_ITEM_SECTION:
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  */
260 static 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 
284  case CONF_ITEM_SECTION:
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  */
317 static 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 
326  case CONF_ITEM_SECTION:
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  */
367 static 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 
456  cf_item_foreach(parent, ci) {
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  */
485  cf_item_foreach(parent, ci) {
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  */
510 CONF_ITEM *_cf_item_next(CONF_ITEM const *ci, CONF_ITEM const *curr)
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  */
525 CONF_ITEM *_cf_item_prev(CONF_ITEM const *ci, CONF_ITEM const *curr)
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  */
540 static 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  */
590 int _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  */
604 char 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  */
632 bool cf_item_is_pair(CONF_ITEM const *ci)
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  */
646 bool cf_item_is_data(CONF_ITEM const *ci)
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 
668  fr_assert(ci->type == CONF_ITEM_PAIR);
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 
708  fr_assert(ci->type == CONF_ITEM_DATA);
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));
823  cs->name2_quote = T_BARE_WORD;
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  */
894 void _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  */
906 void _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) {
947  case CONF_ITEM_SECTION:
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 
969  case CONF_ITEM_INVALID:
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  */
985 {
987 }
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  */
998 {
1000 }
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  */
1011 {
1013 }
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 {
1031  return cf_item_to_section(cf_find(cf_section_to_item(cs), CONF_ITEM_SECTION, name1, name2));
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  */
1120 char 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  */
1139 int8_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  */
1171 char 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  */
1185 char 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  */
1197 char 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  */
1213 char 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  */
1279 CONF_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 
1325  fr_assert(parent);
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  */
1350 int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
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));
1365  talloc_const_free(cp->value);
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 next child that's a #CONF_PAIR
1394  *
1395  * @param[in] cs to return children from.
1396  * @return
1397  * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1398  * - NULL if no #CONF_ITEM matches that criteria.
1399  */
1401 {
1403 }
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  */
1414 {
1416 }
1417 
1418 /** Return the next 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 next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1424  * - NULL if no #CONF_ITEM matches that criteria.
1425  */
1427 {
1429 }
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  */
1439 CONF_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  */
1453 CONF_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  */
1467 CONF_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  */
1486 static 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  */
1520 unsigned 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  */
1540 fr_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  */
1578 char 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  */
1594 char 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  */
1648 static 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  */
1670 static 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  */
1710 CONF_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  */
1728 CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
1729 {
1730  return cf_item_to_data(cf_find_next(ci, prev, CONF_ITEM_DATA, type, name));
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  */
1744 CONF_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 
1751  found = cf_find(parent, CONF_ITEM_DATA, type, name);
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  */
1763 void *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  */
1786 CONF_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  */
1828 CONF_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));
1882  talloc_const_free(cd);
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  */
1897 int _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 
1925 static 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  */
1966 int 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  */
2006 void _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);
2015  fr_vlog(LOG_DST, type, file, line, fmt, aq);
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);
2032  talloc_free(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  */
2045 void _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  */
2068 void _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  */
2157 void _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  */
2180 void _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);
2205  talloc_free(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  */
2219 void _cf_log_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child,
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  */
2274 void _cf_item_debug(CONF_ITEM const *ci)
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 : %u", 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 
2429 void _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:574
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:165
#define RCSID(id)
Definition: build.h:481
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition: build.h:119
#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:110
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:1351
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition: cf_parse.h:570
#define cf_section_rules_push(_cs, _rule)
Definition: cf_parse.h:659
char const * name1
Name of the CONF_ITEM to parse.
Definition: cf_parse.h:565
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:584
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:399
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
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
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_ITEM * _cf_item_remove(CONF_ITEM *parent, CONF_ITEM *child)
Remove item from parent and fixup trees.
Definition: cf_util.c:447
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition: cf_util.c:632
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:664
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
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: cf_util.c:738
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition: cf_util.c:1623
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition: cf_util.c:1578
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
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
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
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
CONF_PAIR * cf_pair_prev(CONF_SECTION const *cs, CONF_PAIR const *curr)
Return the next child that's a CONF_PAIR.
Definition: cf_util.c:1426
void cf_section_debug(CONF_SECTION *cs)
Ease of use from debugger.
Definition: cf_util.c:2406
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
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
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
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
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
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
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
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
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
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
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
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1185
CONF_SECTION * cf_section_first(CONF_SECTION const *cs)
Return the first child in a CONF_SECTION.
Definition: cf_util.c:984
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
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1594
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
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_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
void cf_pair_mark_parsed(CONF_PAIR *cp)
Mark a pair as parsed.
Definition: cf_util.c:1376
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
void _cf_filename_set(CONF_ITEM *ci, char const *filename)
Set the filename of a CONF_ITEM.
Definition: cf_util.c:894
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_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
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
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition: cf_util.c:1763
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
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
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
CONF_SECTION * _cf_root(CONF_ITEM const *ci)
Return the top level CONF_SECTION holding all other CONF_ITEM.
Definition: cf_util.c:558
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_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
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition: cf_util.c:722
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
Definition: cf_util.c:1388
char const * _cf_filename(CONF_ITEM const *ci)
Return the filename the CONF_ITEM was parsed in.
Definition: cf_util.c:604
#define IS_WILDCARD(_ident)
Definition: cf_util.c:76
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:684
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
static void truncate_filename(char const **e, char const **p, int *len, char const *filename)
Definition: cf_util.c:1925
void * _cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd)
Remove data from a configuration section.
Definition: cf_util.c:1872
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
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
void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
Definition: cf_util.c:2429
CONF_ITEM * cf_data_to_item(CONF_DATA const *cd)
Cast CONF_DATA to a CONF_ITEM.
Definition: cf_util.c:754
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
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition: cf_util.c:618
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
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
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
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_PAIR * cf_pair_first(CONF_SECTION const *cs)
Return the next child that's a CONF_PAIR.
Definition: cf_util.c:1400
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp, bool copy_meta)
Duplicate a CONF_PAIR.
Definition: cf_util.c:1321
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
Definition: cf_util.c:1230
CONF_ITEM * _cf_parent(CONF_ITEM const *ci)
Return the parent of a CONF_ITEM.
Definition: cf_util.c:576
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
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1171
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_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_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition: cf_util.c:1197
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
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_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
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
#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
Definition: control_test.c:47
fr_dcursor_iter_t void * current
Definition: dcursor.h:148
fr_dcursor_iter_t iter
Definition: dcursor.h:147
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition: debug.h:216
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_talloc_free_item(fr_dlist_head_t *list_head, void *ptr)
Free the item specified.
Definition: dlist.h:876
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_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_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 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
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
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
static bool done
Definition: radclient.c:80
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_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition: rb.c:824
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition: rb.h:271
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
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:1432
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:1598
#define FR_SBUFF(_sbuff_or_marker)
return count
Definition: module.c:163
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition: talloc.c:660
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition: talloc.c:628
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
Definition: talloc.c:820
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
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
static fr_slen_t data
Definition: value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:997